Ryandor.com

Forums
It is currently Mon Mar 18, 2024 10:17 pm

All times are UTC - 7 hours [ DST ]




Post new topic Reply to topic  [ 23 posts ] 
Author Message
 Post subject: Community WorldMaker
PostPosted: Mon Oct 09, 2006 12:29 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
I hope to have the framework code posted this coming weekend.

I thought I would use this thread as a personal musing of sort, of why some choices are made, etc. I kinda figure this can be place to have dicussions, etc. Hopefully, if there are questions, comments, new threads will be made. I see this one as a monologue of sorts.

The first thing to notice, is the basic question of using any framework. Does one attempt to isolate its usage, to the bare minimum, or fully embrace it, and use it liberally to its maximum benifit. Many attempt to isloate, to facilate reuse of other classes outside the framework. In some of my projects, I have done that as well.

For this project, I have decided to embrace the framework (QT) through out. Just decided I would, no strong reason one way or the other. QT is usable on all three platforms, and free. If one is really going to do something natively on windows or the Mac, they would probably recode it anyway to the language more native to that platform (C#/ObjC).

So for those following along, one should get familar with the QT signal/slot metaphor, as well as their tools!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 11, 2006 4:46 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
I have been toying with making this WorldMaker a client/server design. That would allow multple people over a network to edit the same map (some constraints). Clearly this would be a tad slower then editing locally.

Is there still a desire for this?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 11, 2006 5:45 pm 
Offline
Journeyman
Journeyman

Joined: Sun Dec 29, 2002 4:27 am
Posts: 101
Location: New Zealand
Can I hear a "Hell Yeah!" :D


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 12, 2006 8:38 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
Definately a great direction to go! The ability to collaborate on maps is something that is really needed.

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Thu Oct 12, 2006 5:42 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
Oh, now I have to allow people to collaborate as well? I was planning on people using standard instant messaging for them to do that.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 13, 2006 12:12 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
What I meant was for multiple people to be able to access the same map remotely. :P But a chat or IM interface might be nice too! :)

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 13, 2006 9:53 am 
Offline
Apprentice
Apprentice

Joined: Wed Dec 08, 2004 8:49 am
Posts: 20
Location: Italy
A client/server architecture will be much appreciated. There's no vital need for an integrated chat system, but it would be a nice plus, I'd say first of all we'd like to see a working version without chat and later you can evaluate either it's better to add chat system or something else


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 13, 2006 1:20 pm 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
Yeah, chat is not critical at all. Just a "nice to have". The map editing stuff is what is important.

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 03, 2006 6:50 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
Ok, so it has been a while. Well, I decided I wanted another computer, so that took up a lot of my time, getting my systems all reconfigured.

At this point, I am at a crossroads. I am looking for c++ coders. I am willing to take on worldmaker, but only if there are others coding. If not in he initial developement, taking over for the classes as they are developed.

Why one may ask. Well, I just don't have a need to develop in C++ anymore. So the only motivation to do so, versus ObjC, is if others are going to be involved.

I also believe we need someone who can setup a nice cvs server (or place to post code).


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 4:20 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
I'll help. I am a novice at c++ (actually even less than a novice in all truth) but I am willing to learn and to do what I can to support the project.

The RunUO forums might be a good place to advertise for this also, more coders over there.

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 7:14 am 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
I don't find the Runuo forums to be a place that I enjoy to engage in. It is very focussed on having everyone do something one way (such as why bother coding in anything other then C#).

My experience has been, the emu forums (and associated) as far as development goes, as moved off c++ to c#. And thus, I understand the interest may be miniminum.

FYI, if one wants to do a C# version, I will of course support in any advisory role I can (I just can't code for it).


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 11:04 am 
Offline
Journeyman
Journeyman

Joined: Mon Sep 19, 2005 6:07 pm
Posts: 109
I'd love to help, I still work with C++. My skills are probably where HellRazor's is, or somewhere from n00b to him. This would definately help with our skills and would be something I'd definately be interested in.

Especially the server/network architecture, I believe it would be fantastic to be able to edit the map in real time. That way when one person edits the map, the changes are reflected immediately.

If I was to ever design a whole game engine from scratch for an MORPG, it would include the ability to work on the game in real-time within the client. Similar to how the Hero Engine is. There you have the ability to work on the terrain, client GUI, scripting, etc. within the game environment.

_________________
Demuria Studios


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 11:10 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
OSI's God Client actually has that ability. Only there has only been one version of it ever leaked and its ancient. None of the emulators support it (well except for one called Epsilon which is long dead)!

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 7:02 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
Just to see if this is understandable by all. An example of tiledata class:

Header file

Code:

#ifndef TileData_H
#define TileData_H

#include <fstream>
#include "uoenum.h"



class TileData
{
public:
   
   TileData(const std::string &name="");
   ~TileData();
   bool setFile(const std::string &name);
   bool valid() const;
   
   // parameter checks
   std::string name(enTileType type,short id) const;
   long flags(enTileType type,short id) const;
   bool flag(enTileType type,short id, long flag) const;
   
   // Terrain specific
   short textureId(short id) const;
   
   // Art specific
   unsigned char weight(short id) const;
   char quality(short id) const;
   short unknown(short id) const;
   char unknown1(short id) const;
   char quantity(short id) const;
   unsigned short bodyid(short id) const;
   char unknown2(short id) const;
   unsigned char hue(short id) const;
   unsigned short unknown3(short id) const;
   unsigned char height(short id) const;
   
private:
      long calcIndex(enTileType type, short id) const;
   
private:
   char *ptrData;
   const static short maxId=0x4000;


};
#endif


And the implementation

Code:

#include "TileData.h"
void initEndian();
unsigned short swapUShortToS(unsigned short data);
short swapShortToS(short data);
signed long swapLongToS(signed long data);


TileData::TileData(const std::string &name)
{
   initEndian();
   ptrData=NULL;
   setFile(name);
}
TileData::~TileData()
{
   if (ptrData!=NULL)
      delete [] ptrData;
}

bool TileData::setFile(const std::string &name)
{
   std::fstream file;
   bool status=false;
   if (name.empty())
   {
      if (ptrData!=NULL)
         delete [] ptrData;
      ptrData=NULL;
   }
   else
   {
      file.open(name.c_str(),std::ios_base::in | std::ios_base::binary);
      if (file.is_open())
      {
         std::size_t filesize ;
         file.seekg(0,std::ios::end);
         filesize=file.tellg();
         file.seekg(0,std::ios::beg);
      
         // There are 512 * 836 bytes for terrain informtion
         // The file size should be equal to 512*836 + 512*1188
         if (filesize == 512*(836+1188))
         {
         
            if (ptrData==NULL)
               ptrData=new char[filesize];
            file.read(ptrData,filesize);
            status=true;
         }
         file.close();   
      
      }
   }
   return status;
}
   
bool TileData::valid() const
{
   if (ptrData!=NULL)
      return true;
   return false;
}

long TileData::calcIndex(enTileType type, short id) const
{
   long index=-1;
   if (valid() && index>=0 && index<maxId)
   {
      switch (type)
      {
         case enTerrain:
            index=(id/32)*836 + ((id%32)*26) + 4 ;
            break;
         case enArt:
            index = 512*836 + (id/32)*1188 + ((id%32)*37) + 4;
            
            break;
      }
   }
   return index;
}

long TileData::flags(enTileType type,short id) const
{
   long rvalue=0;
   long index=calcIndex(type,id);
   if (index!=-1)
      rvalue=swapLongToS( *(reinterpret_cast<long*>((ptrData+index))));
   return rvalue;
}
bool TileData::flag(enTileType type,short id, long flag) const
{
   long rvalue=flags(type,id);
   return rvalue&flag!=0?true:false;
}


std::string TileData::name(enTileType type,short id) const
{
   char temp[21];
   temp[20]=0;
   std::string rvalue;
   long index=calcIndex(type,id);
   if (index!=-1)
   {
      int offset=6;
      if (type==enArt)
         offset=17;
      std::memcpy(temp,ptrData+index+offset,20);
      rvalue=temp;
      
   }
   return rvalue;
}

short TileData::textureId(short id) const
{
   short rvalue=0;
   long index=calcIndex(enTerrain,id);
   if (index!=-1)
   {
      rvalue = swapShortToS(*reinterpret_cast<short*>((ptrData+index+4)));
   }
   return rvalue;
}

unsigned char TileData::weight(short id) const
{
   long index=calcIndex(enArt,id);
   unsigned char rvalue=0;
   if (index!=-1)
   {
      rvalue=*(reinterpret_cast<unsigned char*>((ptrData+index+4)));
   }
   return rvalue;
}
char TileData::quality(short id) const
{
   long index=calcIndex(enArt,id);
   char rvalue=0;
   if (index!=-1)
   {
      rvalue=*((ptrData+index+5));
   }
   return rvalue;
}

short TileData::unknown(short id) const
{
   long index=calcIndex(enArt,id);
   short rvalue=0;
   if (index!=-1)
   {
      rvalue=swapShortToS(*(reinterpret_cast<short*>((ptrData+index+6))));
   }
   return rvalue;
}

char TileData::unknown1(short id) const
{
   long index=calcIndex(enArt,id);
   char rvalue=0;
   if (index!=-1)
   {
      rvalue=*((ptrData+index+8));
   }
   return rvalue;
   
}
char TileData::quantity(short id) const
{
   long index=calcIndex(enArt,id);
   char rvalue=0;
   if (index!=-1)
   {
      rvalue=*((ptrData+index+9));
   }
   return rvalue;
   
}
unsigned short TileData::bodyid(short id) const
{
   long index=calcIndex(enArt,id);
   unsigned short rvalue=0;
   if (index!=-1)
   {
      rvalue=swapUShortToS(*(reinterpret_cast<unsigned short*>((ptrData+index+10))));
   }
   return rvalue;
   
}
char TileData::unknown2(short id) const
{
   long index=calcIndex(enArt,id);
   char rvalue=0;
   if (index!=-1)
   {
      rvalue=*((ptrData+index+12));
   }
   return rvalue;
   
}
unsigned char TileData::hue(short id) const
{
   long index=calcIndex(enArt,id);
   unsigned char rvalue=0;
   if (index!=-1)
   {
      rvalue=*(reinterpret_cast<unsigned char*>((ptrData+index+13)));
   }
   return rvalue;
   
}
unsigned short TileData::unknown3(short id) const
{
   long index=calcIndex(enArt,id);
   unsigned short rvalue=0;
   if (index!=-1)
   {
      rvalue=swapUShortToS(*(reinterpret_cast<unsigned short*>((ptrData+index+14))));
   }
   return rvalue;
   
}
unsigned char TileData::height(short id) const
{
   long index=calcIndex(enArt,id);
   unsigned char rvalue=0;
   if (index!=-1)
   {
      rvalue=*(reinterpret_cast<unsigned char*>((ptrData+index+16)));
   }
   return rvalue;
   
}



Hopefully, it is readibly understandable?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Nov 04, 2006 7:07 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
We will need a cache. One of the things we want to do, to gain speed and minimize memory, is to avoid buffer creation/deletion.

These classes, and the one above, are implemented with that thought in mind (why the methods are on the tiledata class, instead of returning a "tile" class to query). If one considers how we plan to use it, a seperate class would be redundant.

This is an unsafe cache. It stores a pointer to the data that is inserted into the cache. It also takes ownership of the pointer. When one fetches from the cache, the ptr is only valid (guaranteed) until the next cache operation. Thus unsafe, but perfectly optimized for what we want to do in WorldMaker.

Code:


#ifndef __PtrCache_H
#define __PtrCache_H

#include <list>
#include <utility>
#ifdef MSC_VER
#include <hash_map>
#define EXTNAMESPACE stdext
#else
#include <ext/hash_map>
#define EXTNAMESPACE __gnu_cxx
#endif
//  This is an unsafe cache.  The ptr it returns for cache data is only valid until the next cache call!
//  Use appropriately!
template<class Key,class Data> class PtrCache
{
public:
   // Some typedefs to make the job easier
   typedef std::list<std::par<Key,Data*> > List;
   typedef typename List::iterator ListIterator ;
   typedef typename List::reverse_iterator ListReverseIterator;
   
   typedef EXTNAMESPACE::hash_map<Key,ListIterator> Map ;
   typedef typename Map::iterator MapIterator ;
   typedef typename Map::const_iterator MapConstIterator;
   
   
private:
   // Actual storage
   List storage;
   Map index;
   const unsigned int max_size;

private:
   // Touch the data, changing its position in the Least Recently Used location;
   void touch(const Key &key)
   {
         MapIterator miter = index.find(key);
         if (miter != index.end())
         {
            storage.splice(storage.begin(),storage,miter->second);
         }
   }
   
   // This erases it from the cache
   Data *erase(const ListIterator iter)
   {
      
      Data *rvalue=NULL;
      if (iter != storage.end())
      {
         MapIterator miter = index.find(iter->first);
         if (miter != index.end())
         {
            index.erase(miter);
         }
         rvalue=(iter->second);
         
         storage.erase(iter);
      }
      return rvalue;
      
   }
   
   
public:
   
   PtrCache(unsigned int value=100): max_size(value)
   {
      
   }
   
   // This calls clear, which invalidates any reference handed out;
   ~PtrCache()
   {
      clear();
   }
   
   // This invalidates any reference handed out
   void clear()
   {
      ListIterator siter = storage.begin();
      while (siter!= storage.end())
      {
         delete siter->second ;
         ++siter;
      }
      // Now clear out all the containers
      storage.clear();
      index.clear();
      pool.clear();
   }
   
   bool contains(const Key &key) const
   {
      MapConstIterator miter = index.find(key);
      if (miter != index.end())
         return true;
      else
         return false;
   }
   
   // Remove the key from the cache, and delete it
   void remove(const Key &key)
   {
      Data *rvalue;
      MapIterator miter = index.find(key);
      if (miter != index.end())
      {
         rvalue=erase(miter->second);
         delete rvalue ;
      }
      
   }
   

   // Return the entry, and remove it from the cache
   Data *take(const Key &key)
   {
      Data *rvalue=NULL;
      MapIterator miter = index.find(key);
      if (miter != index.end())
      {
         rvalue=erase(miter->second);
         
      }
      return rvalue;
   }
   
   // Returns an entry, and remains in the cache
   Data *fetch(const Key &key)
   {
      Data *rvalue=NULL;
      MapIterator miter = index.find(key);
      if (miter != index.end())
      {
         rvalue = (miter->second)->second;
         
      }
      return rvalue;
   }
   
   //
   void insert(const Key &key, Data *data)
   {
      // See if we all ready have this one
      MapIterator miter = index.find(key);
      if (miter!= index.end())
      {
         delete erase(miter->second);
      }
      // Check to see if next one will cause us to exceed the size
      if (storage.size()>= max_size)
      {
         // We need to delete the last one!
         ListReverseIterator sriter= storage.rbegin();
         if (sriter != storage.rend())
         {
            MapIterator miter = index.find(sriter->first);
            if (miter != index.end())
            {
               //
               delete erase(miter->second);
               
            }
         }
         
      }
      // we are now ready to insert
      ListIterator liter = storage.insert(storage.begin(),std::make_pair(key,data));
      index.insert(std::make_pair(key,liter));
      touch(key);
   }
   
   
   
};
#endif



Top
 Profile  
 
 Post subject: Hue
PostPosted: Sat Nov 04, 2006 7:55 pm 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
And the Hue class:

Code:

#ifndef Hue_H
#define Hue_H

#include <string>

class Hue
{
public:
   Hue(const std::string &name="");
   ~Hue();
   bool setFile(const std::string &name);
   short *hue(int id);
   bool valid() const;
   
private:
   char *data;
   int max_id;
   std::size_t buffersize;


};
#endif



And implementation:

Code:
#include "Hue.h"
#include <fstream>
#include <cstdlib>

Hue::Hue(const std::string &name)
{
   data =NULL;
   max_id=0;
   buffersize=0;
   setFile(name);
}

Hue::~Hue()
{
   if (data!=NULL)
      delete[] data;
}

bool Hue::setFile(const std::string &name)
{
   bool status=false;
   if (name.empty())
   {
      if (valid())
      {
         delete[] data;
      }
      data=NULL;
      max_id=buffersize=0;
      status=true;
   }
   else
   {
      std::fstream file;
      file.open(name.c_str(),std::ios_base::in | std::ios_base::binary);
      if (file.is_open())
      {
      
         file.seekg(0,std::ios::end);
         std::size_t filesize=file.tellg();
         file.seekg(0,std::ios::beg);
         // A hue entry takes up 88 bytes. They come in groups of 8, with a 4 byte header;
         max_id=filesize/((88*8)+4);
         // See if we need to make a new buffer
         if ( (data==NULL) || (buffersize != (max_id * ((88*8)+4))) )
         {
            if (data!=NULL)
               delete[] data;
            data = new char[(max_id * ((88*8)+4))];
         }
         buffersize = (max_id * ((88*8)+4));
         max_id=max_id*8 ;
         // max_id now contains the number of hues;
         file.read(data,buffersize);
         
         file.close();
         status=true;
      }
   }
   return status;
}

// This buffer is in small endian, so needs to be converted when used
short *Hue::hue(int id)
{
   short *rvalue=NULL;
   //Hues are 1 indexed, so subtract one;
   --id;
   if (valid() && (id >=0 && id <max_id))
   {
      int offset=(id/8)*((88*8)+4) + (id%8)*(88)+4;
      
      rvalue =  reinterpret_cast<short*>((data+offset));
      
   }
   return rvalue;
}
bool Hue::valid() const
{
   if (data!=NULL)
      return true;
   else
      return false;
}



Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 06, 2006 7:26 am 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
Hopefully the lack of comments indicates the code is clear, and well understood.

The goal is to understood the project as it gets built, so anyone can modify, or maintain it upon completion.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 06, 2006 7:46 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
Well, let's put it this way - I couldn't write all that from scratch myself like you just did (and especially not in C++) - but I can understand most of what you are doing in the code.

The cache code I understand less than the MUL file implementation, although I have a rough idea of what you are doing. Basically I understand the concept but I don't know my C++ well enough to understand the code and how it works.

Can you talk a little bit about how the cache is used in interaction with the MUL files? (Does some of that MUL file code make use of the cache? I haven't gone over it with a fine toothed comb).

(P.S. On a different topic, I need to know what data you need for the Dragon to Map Gen translation table you asked for - do you need RGB values?)

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 06, 2006 9:17 am 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
The cache code will be used for the two main "factories", Textures and art work (both Terrain and Art). Not posted yet, but will be there shortly.

Bascially we will be making repeated calls for the same image. Image collection is an "expensive" call, it creates memory, etc. So, we want to cache them to some extent. It will become clearer when the factories get posted that use them.

The cache is an Least Recently Used type. It has two storage, a list and a map. The list maintains the order of use (and the data itself). The last used is on top of the list, and the one that has been the longest since used is at the bottom of the least. The map is a quick way to see if in the cache.



Don't worry about not being able to generate from scratch. you dont have to ! But hopefully you do understand enough to modify later, or fix bugs. And after a bit, you could generate them scratch.

The base image files follow:

Base class for images:

Code:

#ifndef Image_H
#define Image_H

#include <utility>
#include "uoenum.h"


class Hue;

class Image
{
public:
   enum enPixelFormat {enRGBA,enARGB,enBGRA,enABGR};

   

   Image(int i,  char *d,Hue *hh,enTileType tt,bool p);
   ~Image();
   std::pair<int,int> size();
   virtual bool format(long *buffer, int hue=0, unsigned char alpha=255,bool flipped=false,int w=0,int h=0,enPixelFormat=enRGBA)=0;
   int imageId() const;
   enTileType type() const;
   
protected:
   long convert16To32Color(short native,unsigned char alpha=255,enPixelFormat format=enRGBA);
   short applyHue(short native,short *hueBuffer,bool partial);
   
   short * getHue(int h);
   
   void setSize(int w, int h);
   void setPartial(bool b);
   
protected:
      
   Hue *hueData ;

   char *data;
   int myid;
   int mywidth;
   int myheight;
   enTileType mytype;
   
   bool mypartial;


};
#endif



Image implementation

Code:
#include "Image.h"
#include "Hue.h"


short swapShortToN(short data);

Image::Image(int i,  char *d,Hue *hh,enTileType tt,bool p)
{
   myid=i;
   mywidth = 0;
   myheight =0;
   data = d;
   mypartial=p;
   hueData =hh;
   mytype=tt;
}
void Image::setSize(int w, int h)
{
   mywidth=w;
   myheight=h;
}

Image::~Image()
{
   if (data!=NULL)
      delete [] data;
}

std::pair<int,int> Image::size()
{
   return std::make_pair(mywidth,myheight);
}

int Image::imageId() const
{
   return myid;
}

enTileType Image::type() const
{
   return mytype;
}

long Image::convert16To32Color(short native,unsigned char alpha,enPixelFormat format)
{
   long color32;
   short shiftRed;
   short shiftBlue;
   short shiftGreen;
   short shiftAlpha;
   switch (format)
   {
      case enARGB:
         shiftRed=16;
         shiftBlue=0;
         shiftGreen=8;
         shiftAlpha=24;
         break;
         
      case enRGBA:
         shiftRed=24;
         shiftBlue=8;
         shiftGreen=16;
         shiftAlpha=0;
         break;
         
      case enBGRA:
         shiftRed=8;
         shiftBlue=24;
         shiftGreen=16;
         shiftAlpha=0;
         break;
         
      case enABGR:
         shiftRed=0;
         shiftBlue=16;
         shiftGreen=8;
         shiftAlpha=24;
         break;
         
   }
   // This assumes the 16 bit color is in the native endian of the machine
   
   color32 = (((0x1f&native)*8)<<shiftBlue) |  ((((0x3e0&native)>>5)*8)<<shiftGreen)
      |  ((((0x7c00&native)>>10)*8)<<shiftRed) | (alpha<<shiftAlpha);
   return color32;
   
}

// color is assumed in the native endian, but the huebuffer is not (it is assumed to be small endian always)
// The returns native endian
short Image::applyHue(short native,short *hueBuffer,bool partial)
{
   short color = native;
   if (hueBuffer != NULL )
   {
      if (partial)
      {
         if ( ((native>>10)&0x1f) == ((native>>5)&0x1f) == (native&0x1f) )
             color = swapShortToN(  hueBuffer[ (native>>10)&0x1f] );
         
      }
      else
      {
         color = swapShortToN(  hueBuffer[ (native>>10)&0x1f] );
      }
      
   }
   return color;
}

short * Image::getHue(int h)
{
   short *rvalue=NULL;
   if (h>0 &&  hueData != NULL)
   {
      rvalue=(*hueData).hue(h) ;
   }
   return rvalue;
}



Now the actual classes for images:

Texture's

Code:
#ifndef TexImage_H
#define TexImage_H

#include "Image.h"

class TexImage : public Image
{

public:
   TexImage(int i, long extra, char *d,Hue *hh);
   virtual bool format(long *buffer, int hue=0, unsigned char alpha=255,bool flipped=false,int w=0,int h=0,Image::enPixelFormat=enRGBA);
   

};
#endif



Texture Implementation
Code:
#include "TexImage.h"
#include <string>

signed short swapShortToN(signed short data);

TexImage::TexImage(int i, long extra, char *d,Hue *hh) : Image(i, d,hh,enTexture,false)
{
   int s = extra == 1 ? 128:64 ;
   setSize(s,s);
}
bool TexImage::format(long *buffer, int hue, unsigned char alpha,bool flipped,int w,int h,Image::enPixelFormat pixelFormat)
{
   int width ;
   int height;
   bool status = false;
   short *raw = reinterpret_cast<short*>(data);
   short *hueBuffer = getHue(hue);
   if (w==0)
      w=mywidth;
   if (h==0)
      h=myheight;
   
   if (w>0 && w<=mywidth && h>0 && h<=myheight)
   {
      status=true;
      width=w;
      height=h;
      int dir=-1;
      int start=(height-1);

      if (flipped)
      {
         start = 0;
         dir =1;
      }
      
      long y,x;
      std::memset(buffer,0,width*height*4);
      for (y=0; y<height;++y)
      {
         for (x=0;x<width;++x)
         {
            
            raw[(start+dir*y)*width + x]= convert16To32Color( applyHue(swapShortToN(raw[y*mywidth+x]),hueBuffer,mypartial), alpha, pixelFormat) ;
         }
      }
   }
   return status;
   
}


Terrain image
Code:
#ifndef TerrainImage_H
#define TerrainImage_H

#include "Image.h"

class TerrainImage : public Image
{

public:
   TerrainImage(int i, char *d, Hue *h, bool partial);
   virtual bool format(long *buffer, int hue=0, unsigned char alpha=255,bool flipped=false,int w=0,int h=0,enPixelFormat=enRGBA);

};
#endif




Terrain implementation

Code:
#include <string>

signed short swapShortToN(signed short data);


TerrainImage::TerrainImage(int i, char *d, Hue *h, bool partial) : Image(i,d,h,enTerrain,partial)
{
   setSize(44,44);
}



bool TerrainImage::format(long *buffer, int hue, unsigned char alpha,bool flipped,int w,int h,Image::enPixelFormat pixelFormat)
{
   int width ;
   int height;
   bool status = false;
   short *raw = reinterpret_cast<short*>(data);
   short *hueBuffer = getHue(hue);
   if (w==0)
      w=mywidth;
   if (h==0)
      h=myheight;
   
   if (w>0 && w<=mywidth && h>0 && h<=myheight)
   {
      status=true;
      width=w;
      height=h;
      int dir=-1;
      int start=(height-1);
      
      if (flipped)
      {
         start = 0;
         dir =1;
      }
      
      // Clear out what is there
      std::memset(buffer,0,width*height*4);
      
      long offset=0;
      long run=2;
      long x=22;
      for (int j=0;j<22;++j)
      {
         --x;
         for (int draw=0;draw<run;++draw)
         {
            if ((j<height) &&  ((x+draw) < width) )
               buffer[x+draw + (start + dir*j)*44] = convert16To32Color( applyHue( swapShortToN(raw[offset]), hueBuffer, mypartial), alpha, pixelFormat) ;
            ++offset;
         }
         run+=2;

         
      }
      
      run=44;
      x=0;
      for (int j=22; j<44;++j)
      {
         
         for (int draw=0;draw<run;++draw)
         {
            if ((j<height) &&  ((x+draw) < width) )
               buffer[x+draw + (start +dir*j)*44] = convert16To32Color( applyHue( swapShortToN(raw[offset]), hueBuffer, mypartial), alpha, pixelFormat) ;
            ++offset;
         }
         ++x;
         run -=2;
         
      }
      
   }
   return status;
}



And Art images

Code:

#ifndef ArtImage_H
#define ArtImage_H
#include "Image.h"

class ArtImage : public Image
{
public:
   ArtImage(int i, char *d, Hue *h, bool partial);
   virtual bool format(long *buffer, int hue=0, unsigned char alpha=255,bool flipped=false,int w=0,int h=0,enPixelFormat=enRGBA);
   


};
#endif



Art implementation

Code:

#include "ArtImage.h"

#include <string>

signed short swapShortToN(signed short data);
signed long swapLongToN(signed long data);


ArtImage::ArtImage(int i, char *d, Hue *h, bool partial) : Image(i,d,h,enArt,partial)
{
   int w= swapShortToN(*reinterpret_cast<short*>((data+4)) );
   int hh= swapShortToN(*reinterpret_cast<short*>((data+6)) );
   setSize(w,hh);
   
}



bool ArtImage::format(long *buffer, int hue, unsigned char alpha,bool flipped,int w,int h,Image::enPixelFormat pixelFormat)
{
   int width ;
   int height;
   bool status = false;
   short *input = reinterpret_cast<short*>(data+4);
   short *hueBuffer = getHue(hue);
   if (w==0)
      w=mywidth;
   if (h==0)
      h=myheight;
   
   if (w>0 && w<=mywidth && h>0 && h<=myheight)
   {
      status=true;
      width=w;
      height=h;
      int dir=-1;
      int start=(height-1);
      
      if (flipped)
      {
         start = 0;
         dir =1;
      }
      
      // Clear out what is there
      std::memset(buffer,0,width*height*4);
      int streamloc = 2+myheight ;
      int index ;
      
      int X=0 ;
      int Y=0 ;
      for ( Y=0; Y < height ; ++Y )
      {
         X=0 ;
         
         index = (2 +Y) ;
         short offset ;
         offset = swapShortToN(input[index])  ;
         index = streamloc + offset ;
         short xOffset ;
         xOffset=0 ;
         short xRun ;
         xRun=1;
         short runColor ;
         xRun = xOffset = 1 ;
         while ( xOffset+xRun !=0 )
         {
            xOffset = swapShortToN(input[index]) ;
            ++index      ;
            xRun = swapShortToN(input[index]) ;
            ++index ;
            if ( (xOffset+xRun!=0) )
            {
               X+=xOffset ;
               for ( short jj=0; jj < xRun; ++jj )
               {
                  int pixel = X + ((start+dir*Y)*mywidth) ;
                  // We don't draw if the color is pure black
                  runColor = swapShortToN(input[index]);
                  if (runColor&0x7FFF !=0 && X<width)
                  {
                     runColor=  applyHue(swapShortToN(input[index]),hueBuffer,mypartial) ;
                     data[pixel] =convert16To32Color(runColor,alpha,pixelFormat) ;
                  }
                  ++index ;
                  ++X ;
               }
            }
         }
      }
            
   }
   return status;
}



Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 07, 2006 11:50 am 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
Ok, now for the factories. These are what generate the images:

TerrainArtFactory.h
Code:
// Copyright (c) 2006, Charles M. Kerr
// All rights reserved.
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   ?   Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//   ?   Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//   ?   Neither the name of WorldMaker nor the names of its contributors may be used
//      to endorse or promote products derived from this software without specific
//      prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//

#ifndef TerrainArtFactory_H
#define TerrainArtFactory_H
#include <string>
#include <vector>
#include <fstream>

#include "uoenum.h"
#include "PtrCache.h"

class ArtImage;
class TerrainImage;
class Hue;
class TileData;
class Image;

class TerrainArtFactory
{
public:
   TerrainArtFactory(const std::string &idx, const std::string &mul, Hue *hue, TileData *tile);
   bool setFile(const std::string &idx, const std::string &mul);
   
   ~TerrainArtFactory();
   
   bool valid() const;
   
   std::vector<long> validIds(enTileType type) const;
   
   
   ArtImage* getArt(long id);
   TerrainImage *getTerrain(long id);
   
protected:
      
      void buildValid();
   
   
protected:
   long *data;
   std::fstream mulfile;
   
   PtrCache<long, Image> cache[2];
   
   Hue *hueData;
   TileData *tileData;
   
   std::vector<long> valid_id[2];
   


};
#endif



Impementation
Code:
// Copyright (c) 2006, Charles M. Kerr
// All rights reserved.
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   ?   Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//   ?   Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//   ?   Neither the name of WorldMaker nor the names of its contributors may be used
//      to endorse or promote products derived from this software without specific
//      prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//

#include "TerrainArtFactory.h"

#include "Hue.h"
#include "TileData.h"
#include "TerrainImage.h"
#include "ArtImage.h"

signed long swapLongToN(signed long data);
void initEndian();

#define MAX_ID 0x4000


TerrainArtFactory::TerrainArtFactory(const std::string &idx, const std::string &mul, Hue *hue, TileData *tile)
{
   data = NULL;
   hueData = hue;
   tileData = tile;
   setFile(idx,mul);
   initEndian();
}

bool TerrainArtFactory::setFile(const std::string &idx, const std::string &mul)
{
   bool status = false;
   // We dont anticipate a lot of file changing, so we are not going to worry
   // about optimizing memory reuse here
   if (data!=NULL)
      delete[] data;
   if (mulfile.is_open())
      mulfile.close();
   mulfile.open(mul.c_str(),std::ios_base::in | std::ios_base::binary) ;
   if (mulfile.is_open())
   {
      std::fstream idxfile;
      idxfile.open(idx.c_str(), std::ios_base::in | std::ios_base::binary) ;
      if (!idxfile.is_open())
      {
         mulfile.close();
      }
      else
      {
         idxfile.seekg(0,std::ios::end);
         std::size_t filesize= idxfile.tellg();
         idxfile.seekg(0,std::ios::beg);

         // The art file is larger then we need (it has old beta sprite animations)
         // The larget valid tile id is 0x4000 for either Terrain or Art.
         if (filesize >= (0x4000*24))
         {
            status=true;

            data = new long[0x8000];
         
            idxfile.read(reinterpret_cast<char*>(data),0x8000*4);
            idxfile.close();
         
            buildValid();
         }
         
      }
   }
   return status;
}

TerrainArtFactory::~TerrainArtFactory()
{
   if (data !=NULL)
      delete[] data;
   if (mulfile.is_open())
      mulfile.close();
   cache[0].clear();
   cache[1].clear();
}


bool TerrainArtFactory::valid() const
{
   if (data!=NULL && mulfile.is_open())
      return true;
   else
      return false;
}

std::vector<long> TerrainArtFactory::validIds(enTileType type) const
{
   switch (type)
   {
      case enTerrain:
         return valid_id[type];
         break;
      case enArt:
         return valid_id[type];
         break;
      default:
         return std::vector<long>();
   }
}


void TerrainArtFactory::buildValid()
{
   valid_id[0].clear();
   valid_id[1].clear();
   long *ptr=data;
   long index;
   long length;
   for (int i=0;i<2;++i)
   {
      for (long j=0;j<MAX_ID;++j)
      {
         index = swapLongToN(*ptr);
         ++ptr;
         length = swapLongToN(*ptr);
         ptr +=2;
         if (index >-1 && length >0)
            valid_id[i].push_back(j);
      }
      
   }
}
ArtImage* TerrainArtFactory::getArt(long id)
{
   ArtImage *rvalue=NULL;
   long *ptr = data+0x4000*3;
   if (valid() && id >=0 && id < MAX_ID)
   {
      // first check the cache see if it is in there
      if (cache[1].contains(id))
         rvalue=reinterpret_cast<ArtImage*>(cache[1].fetch(id));
      else
      {
         long index = swapLongToN(*(ptr+3*id));
         long length = swapLongToN(*(ptr+3*id+1));
         if (index >-1 && length >0)
         {
            mulfile.seekg(index,std::ios::beg);
            char *buffer = new char[length];
            mulfile.read(buffer,length);
            // Now great a ArtImage
            rvalue = new ArtImage(id,buffer,hueData, (*tileData).flag(enArt,id,enPartialHue) );
            // and insert into the cache for next time
            cache[1].insert(id,rvalue);
         }
      }
      
   }
   return rvalue;
   
}


TerrainImage* TerrainArtFactory::getTerrain(long id)
{
   TerrainImage *rvalue=NULL;
   long *ptr = data;
   if (valid() && id >=0 && id < MAX_ID)
   {
      // first check the cache see if it is in there
      if (cache[0].contains(id))
         rvalue=reinterpret_cast<TerrainImage*>(cache[1].fetch(id));
      else
      {
         long index = swapLongToN(*(ptr+3*id));
         long length = swapLongToN(*(ptr+3*id+1));
         if (index >-1 && length >0)
         {
            mulfile.seekg(index,std::ios::beg);
            char *buffer = new char[length];
            mulfile.read(buffer,length);
            // Now great a TerrainImage
            rvalue = new TerrainImage(id,buffer,hueData, (*tileData).flag(enTerrain,id,enPartialHue) );
            // and insert into the cache for next time
            cache[0].insert(id,rvalue);
         }
      }
      
   }
   return rvalue;
   
}



Texture factory

Code:

// Copyright (c) 2006, Charles M. Kerr
// All rights reserved.
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   ?   Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//   ?   Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//   ?   Neither the name of WorldMaker nor the names of its contributors may be used
//      to endorse or promote products derived from this software without specific
//      prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//

#ifndef TexFactory_H
#define TexFactory_H


#include <fstream>
#include <string>
#include <vector>

class TexImage;
class Hue;
class TileData;

#include "PtrCache.h"

class TexFactory
{
public:
   TexFactory(const std::string &idx, const std::string &mul, Hue *hue, TileData *tile);
   bool setFile(const std::string &idx, const std::string &mul);
   
   ~TexFactory();
   
   bool valid() const;
   
   std::vector<long> validIds() const;
   
   long maxId() const;
   
   TexImage* getTexture(long id);
   
protected:
      
   void buildValid();
   
   
protected:
   long *data;
   std::fstream mulfile;
   
   long max_id;
   PtrCache<long, TexImage> cache;
   
   Hue *hueData;
   TileData *tileData;
   
   std::vector<long> valid_id;


};
#endif



And implementation

Code:
// Copyright (c) 2006, Charles M. Kerr
// All rights reserved.
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   ?   Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//   ?   Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//   ?   Neither the name of WorldMaker nor the names of its contributors may be used
//      to endorse or promote products derived from this software without specific
//      prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//

#include "TexFactory.h"
#include "Hue.h"
#include "TileData.h"
#include "TexImage.h"
signed long swapLongToN(signed long data);
void initEndian();


TexFactory::TexFactory(const std::string &idx, const std::string &mul, Hue * hue,  TileData *tile)
{
   data = NULL;
   max_id=0;
   hueData = hue;
   tileData = tile;
   setFile(idx,mul);
   initEndian();
}

bool TexFactory::setFile(const std::string &idx, const std::string &mul)
{
   bool status = false;
   // We dont anticipate a lot of file changing, so we are not going to worry
   // about optimizing memory reuse here
   if (data!=NULL)
      delete[] data;
   if (mulfile.is_open())
      mulfile.close();
   mulfile.open(mul.c_str(),std::ios_base::in | std::ios_base::binary) ;
   if (mulfile.is_open())
   {
      std::fstream idxfile;
      idxfile.open(idx.c_str(), std::ios_base::in | std::ios_base::binary) ;
      if (!idxfile.is_open())
      {
         mulfile.close();
      }
      else
      {
         status=true;
         idxfile.seekg(0,std::ios::end);
         std::size_t filesize= idxfile.tellg();
         idxfile.seekg(0,std::ios::beg);
         max_id = filesize/12;
         
         data = new long[filesize/4];
         
         idxfile.read(reinterpret_cast<char*>(data),filesize);
         idxfile.close();
         
         buildValid();
         
      }
   }
   return status;
}

TexFactory::~TexFactory()
{
   if (data !=NULL)
      delete[] data;
   if (mulfile.is_open())
      mulfile.close();
   cache.clear();
}


bool TexFactory::valid() const
{
   if (data!=NULL && mulfile.is_open())
      return true;
   else
      return false;
}

std::vector<long> TexFactory::validIds() const
{
   return valid_id;
}

long TexFactory::maxId() const
{
    if (valid())
       return max_id-1;
    else
       return 0;
}

void TexFactory::buildValid()
{
   valid_id.clear();
   long *ptr=data;
   long index;
   long length;
   for (long j=0;j<max_id;++j)
   {
      index = swapLongToN(*ptr);
      ++ptr;
      length = swapLongToN(*ptr);
      ptr +=2;
      if (index >-1 && length >0)
         valid_id.push_back(j);
   }
}

TexImage* TexFactory::getTexture(long id)
{
   TexImage *rvalue=NULL;
   if (valid() && id >=0 && id < max_id)
   {
      // first check the cache see if it is in there
      if (cache.contains(id))
         rvalue=cache.fetch(id);
      else
      {
         long index = swapLongToN(*(data+3*id));
         long length = swapLongToN(*(data+3*id+1));
         long extra = swapLongToN(*(data+3+id+2));
         if (index >-1 && length >0)
         {
            mulfile.seekg(index,std::ios::beg);
            char *buffer = new char[length];
            mulfile.read(buffer,length);
            // Now great a TexImage
            rvalue = new TexImage(id,extra,buffer,hueData);
            // and insert into the cache for next time
            cache.insert(id,rvalue);
         }
      }
      
   }
   return rvalue;

}



Now a little class to wrapper all the factories, user convience:
Code:

// Copyright (c) 2006, Charles M. Kerr
// All rights reserved.
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   ?   Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//   ?   Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//   ?   Neither the name of WorldMaker nor the names of its contributors may be used
//      to endorse or promote products derived from this software without specific
//      prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//

#ifndef ImageFactory_H
#define ImageFactory_H

class Hue;
class TileData;
class TerrainArtFactory;
class TexFactory;
class Image;

#include <string>
#include <vector>
#include "uoenum.h"

class ImageFactory
{
public:
   ImageFactory(TileData * t, const std::string &huefile, const std::string &texidx, const std::string &texmul,
             const std::string &artidx, const std::string &artmul);

   ~ImageFactory();
   Image *getImage(enTileType type,long id);
   
   std::vector<long> getValid(enTileType type) const;
   
   bool valid() const;
   
   bool setHueFile(const std::string &name);
   bool setTexmap(const std::string &idx, const std::string &mul);
   bool setArt(const std::string &idx, const std::string &mul);
   
   
protected:
   
   Hue *hueData;
   TileData *tileData;
   TexFactory *texFactory;
   TerrainArtFactory *artFactory;


};
#endif



Implementation
Code:
// Copyright (c) 2006, Charles M. Kerr
// All rights reserved.
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//   ?   Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//   ?   Redistributions in binary form must reproduce the above copyright notice,
//      this list of conditions and the following disclaimer in the documentation
//      and/or other materials provided with the distribution.
//   ?   Neither the name of WorldMaker nor the names of its contributors may be used
//      to endorse or promote products derived from this software without specific
//      prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//

#include "ImageFactory.h"
#include "Hue.h"
#include "TileData.h"
#include "TexFactory.h"
#include "TerrainArtFactory.h"
#include "Image.h"
#include "ArtImage.h"
#include "TerrainImage.h"


ImageFactory::ImageFactory(TileData * t, const std::string &huefile, const std::string &texidx, const std::string &texmul,
                      const std::string &artidx, const std::string &artmul)
{
   hueData = new Hue(huefile);
   texFactory = new TexFactory(texidx,texmul,hueData,t);
   artFactory = new TerrainArtFactory(artidx,artmul,hueData,t);
}

ImageFactory::~ImageFactory()
{
   delete hueData;
   delete texFactory;
   delete artFactory;
}

Image *ImageFactory::getImage(enTileType type,long id)
{
   Image *rvalue=NULL;
   if (valid())
   {
      switch(type)
      {
         case enTerrain:
            rvalue = ( ((*artFactory).getTerrain(id)) );
            break;
            
         case enArt:
            rvalue= ( ((*artFactory).getArt(id)) );
            
            break;
         case enTexture:
            rvalue=  reinterpret_cast<Image*>( ((*texFactory).getTexture(id)) );
            
            break;
      }
   }
   return rvalue;
      
   
}

std::vector<long> ImageFactory::getValid(enTileType type) const
{
   if (valid())
   {
      switch(type)
      {
         case enTerrain:
         case enArt:
            return (*artFactory).validIds(type);
         case enTexture:
            return (*texFactory).validIds();
         default:
            return std::vector<long>();
      }
      
   }
   else
      return std::vector<long>();
}

bool ImageFactory::valid() const
{
   return (*hueData).valid() && (*texFactory).valid() && (*artFactory).valid() ;
}


bool ImageFactory::setHueFile(const std::string &name)
{
   return (*hueData).setFile(name);
}
bool ImageFactory::setTexmap(const std::string &idx, const std::string &mul)
{
   return (*texFactory).setFile(idx,mul);
}
bool ImageFactory::setArt(const std::string &idx, const std::string &mul)
{
   return (*artFactory).setFile(idx,mul);
}



This is all pure c++, and should work on any platform.

I acknowneldge I could have done endian swapping via compile (and would have been faster for little endian machines). For me however, I have to build universal binaries on the Mac, and dont want to worry about compilier defines at the moment (perhaps later I will or someone will retrofit that, it is easy enough).


Again, if any questions, please feel free to ask. The goal is for this to be a community project. As I don't/can't run windows anymore, clearly one will need to test and build for the windows platform as we progress. This project will be layed out to only require free tools (one can use others as they desire). So mingw, QT GPL version, XCode (mac), etc. This basiclly is all the graphics data code that is needed. The only other mul data code would be the map/static file handlers.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 1:39 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
I'll make an attempt to bring all this into a MS Visual C++ program soon.

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 8:08 am 
Offline
Grand Master
Grand Master

Joined: Sat Mar 12, 2005 3:29 pm
Posts: 414
One thing to note, if you are going to use VS , the free QT doesn't support it out of the box.

One may have to go here: http://qtnode.net/wiki/Qt4_with_Visual_Studio


Last edited by punt1959 on Wed Nov 08, 2006 1:48 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 8:30 am 
Offline
Grand Master
Grand Master

Joined: Thu Jul 17, 2003 8:54 am
Posts: 971
Hmmm, link isn't working. Could be my firewall at work tho.

_________________
-= HellRazor =-
Shattered Sosaria is coming!
http://www.shatteredsosaria.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ] 

All times are UTC - 7 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group