1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-20 20:29:10 +00:00

Merged in cwalther/cwe/cursors2 (pull request #10)

Improved Cursors

This is the second attempt at getting the following improvements to the Uru mouse cursors into CWE-ou:

* fix the blurriness
* add a subtle shadow to fix cursors being invisible on light backgrounds
* cleaner, more regular appearance

A (slightly outdated) picture for comparison is at http://forums.openuru.org/viewtopic.php?t=558&p=4265#p4265 , and anyone who has played on Gehn, TOC, or any other shard using the H'uru client has already seen the new cursors.

In order to do this properly, in a way that will continue to work in a cross-platform future, a lot of work done by Deledrius in the H'uru fork is included: He added PNG support to Plasma and introduced a client resource manager that loads resources such as the cursors, but also voice chat indicators and the loading linking book animation, which were also replaced by higher-quality recreations, fromfile instead of from Windows resources. resource.data

This also opens the way for other applications of PNG, such as saving the local copies of KI pictures in a lossless format instead of the heavily compressed JPEG we currently have.

Note: the new code requires a newer version of libpng than included with the CWE sources. Like other library dependencies, this must be installed separately. Instructions for that are at http://wiki.openuru.org/index.php?title=Build_the_client_with_MSVC_2003#Build_steps .
This commit is contained in:
Christian Walther
2012-10-13 00:28:09 +02:00
252 changed files with 4896 additions and 70915 deletions

View File

@ -66,8 +66,8 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plPipeline/plDebugText.h"
#include "../plStatusLog/plStatusLog.h"
#define MICROPHONE 121
#define TALKING 122
#define MICROPHONE "ui_microphone.png"
#define TALKING "ui_speaker.png"
#define NUM_CHANNELS 1
#define VOICE_STOP_MS 2000
#define MAX_DATA_SIZE 1024 * 4 // 4 KB
@ -84,13 +84,13 @@ hsBool plVoicePlayer::fEnabled = true;
plVoiceRecorder::plVoiceRecorder()
{
plPlateManager::Instance().CreatePlate( &fDisabledIcon );
fDisabledIcon->CreateFromResource( MAKEINTRESOURCE( MICROPHONE ) );
fDisabledIcon->CreateFromResource( MICROPHONE );
fDisabledIcon->SetPosition(-0.90, -0.90);
fDisabledIcon->SetSize(0.0675, 0.09);
fDisabledIcon->SetVisible(false);
plPlateManager::Instance().CreatePlate( &fTalkIcon );
fTalkIcon->CreateFromResource( MAKEINTRESOURCE( TALKING ) );
fTalkIcon->CreateFromResource( TALKING );
fTalkIcon->SetPosition(-0.9,-0.9);
fTalkIcon->SetSize(0.0675, 0.09);
fTalkIcon->SetVisible(false);
@ -208,7 +208,7 @@ void plVoiceRecorder::DrawDisabledIcon(hsBool b)
plPlateManager::Instance().CreatePlate( &fDisabledIcon );
if (fDisabledIcon)
{
fDisabledIcon->CreateFromResource( MAKEINTRESOURCE( MICROPHONE ) );
fDisabledIcon->CreateFromResource( MICROPHONE );
fDisabledIcon->SetPosition(-0.90, -0.90);
fDisabledIcon->SetSize(0.0675, 0.09);
fDisabledIcon->SetVisible(false);
@ -225,7 +225,7 @@ void plVoiceRecorder::DrawTalkIcon(hsBool b)
{
plPlateManager::Instance().CreatePlate( &fTalkIcon );
if (fTalkIcon)
{ fTalkIcon->CreateFromResource( MAKEINTRESOURCE( TALKING ) );
{ fTalkIcon->CreateFromResource( TALKING );
fTalkIcon->SetPosition(-0.9,-0.9);
fTalkIcon->SetSize(0.0675, 0.09);
fTalkIcon->SetVisible(false);

View File

@ -0,0 +1,152 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsUtils.h"
#include "hsStream.h"
#include "hsResMgr.h"
#include "plJPEG/plJPEG.h"
#include "plGImage/plPNG.h"
#include "plGImage/plMipmap.h"
#include "plClientResMgr.h"
//// Singleton Instance ///////////////////////////////////////////////////////
plClientResMgr& plClientResMgr::Instance(void)
{
static plClientResMgr theInstance;
return theInstance;
}
plClientResMgr::plClientResMgr()
{
this->ClientResources = TRACKED_NEW std::map<std::string, plMipmap*>;
}
plClientResMgr::~plClientResMgr()
{
if (this->ClientResources) {
std::map<std::string, plMipmap*>::iterator it;
for (it = this->ClientResources->begin(); it != this->ClientResources->end(); ++it) {
if (it->second)
it->second->UnRef();
}
delete this->ClientResources;
}
}
void plClientResMgr::ILoadResources(const char* resfile)
{
if (!resfile) {
return;
}
wchar* wFilename = hsStringToWString(resfile);
hsUNIXStream in;
if (in.Open(wFilename, L"rb")) {
UInt32 header = in.ReadSwap32();
UInt32 version = in.ReadSwap32();
UInt32 num_resources = 0;
switch (version) {
case 1:
num_resources = in.ReadSwap32();
for (int i = 0; i < num_resources; i++) {
plMipmap* res_data = NULL;
UInt32 res_size = 0;
char* tmp_name = in.ReadSafeStringLong();
std::string res_name = std::string(tmp_name);
std::string res_type = res_name.substr(res_name.length() - 4, 4);
delete tmp_name;
// Version 1 doesn't encode format, so we'll try some simple
// extension sniffing
if (res_type == ".png") {
// Read resource stream size, but the PNG has that info in the header
// so it's not needed
res_size = in.ReadSwap32();
res_data = plPNG::Instance().ReadFromStream(&in);
} else if (res_type == ".jpg") {
// Don't read resource stream size, as plJPEG's reader will need it
res_data = plJPEG::Instance().ReadFromStream(&in);
} else {
// Original Myst5 format only is known to support Targa,
// so default fallback is targa
// TODO - Add plTarga::ReadFromStream()
// for now, just skip the unknown resource and put NULL into the map
res_size = in.ReadSwap32();
in.Skip(res_size);
}
(*this->ClientResources)[res_name] = res_data;
}
break;
default:
break;
}
in.Close();
}
delete wFilename;
}
plMipmap* plClientResMgr::getResource(const char* resname)
{
plMipmap* resmipmap = NULL;
std::map<std::string, plMipmap*>::iterator it = this->ClientResources->find(resname);
if (it != this->ClientResources->end()) {
resmipmap = it->second;
} else {
hsAssert(resmipmap, "Unknown client resource requested.");
}
return resmipmap;
}

View File

@ -0,0 +1,66 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _plClientResMgr_h
#define _plClientResMgr_h
#include <map>
#include <string>
class plMipmap;
class plClientResMgr {
protected:
std::map<std::string, plMipmap*>* ClientResources;
public:
plClientResMgr();
~plClientResMgr();
void ILoadResources(const char* resfile);
plMipmap* getResource(const char* resname);
static plClientResMgr& Instance(void);
};
#endif // _plClientResMgr_

View File

@ -0,0 +1,270 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsStream.h"
#include "hsExceptions.h"
#include "hsUtils.h"
#include "plPNG.h"
#include "../plGImage/plMipmap.h"
#include <png.h>
#define PNGSIGSIZE 8
// Custom functions to read and write data from or to an hsStream
// used by libPNG's respective functions
void pngReadDelegate(png_structp png_ptr, png_bytep png_data, png_size_t length)
{
hsStream* inStream = (hsStream*)png_get_io_ptr(png_ptr);
inStream->Read(length, (UInt8*)png_data);
}
void pngWriteDelegate(png_structp png_ptr, png_bytep png_data, png_size_t length)
{
hsStream* outStream = (hsStream*)png_get_io_ptr(png_ptr);
outStream->Write(length, (UInt8*)png_data);
}
//// Singleton Instance ///////////////////////////////////////////////////////
plPNG& plPNG::Instance(void)
{
static plPNG theInstance;
return theInstance;
}
//// IRead ////////////////////////////////////////////////////////////////////
// Given an open hsStream, reads the PNG data off of the
// stream and decodes it into a new plMipmap. The mipmap's buffer ends up
// being a packed RGBA buffer.
// Returns a pointer to the new mipmap if successful, NULL otherwise.
plMipmap* plPNG::IRead(hsStream* inStream)
{
plMipmap* newMipmap = NULL;
png_structp png_ptr;
png_infop info_ptr;
png_infop end_info;
try {
// Check PNG Signature
png_byte sig[PNGSIGSIZE];
inStream->Read8Bytes((char*) sig);
if (!png_sig_cmp(sig, 0, PNGSIGSIZE)) {
// Allocate required structs
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
throw(false);
}
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
throw(false);
}
end_info = png_create_info_struct(png_ptr);
if (!end_info) {
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
throw(false);
}
// Assign delegate function for reading from hsStream
png_set_read_fn(png_ptr, (png_voidp)inStream, pngReadDelegate);
// Get PNG Header information
png_set_sig_bytes(png_ptr, PNGSIGSIZE);
png_read_info(png_ptr, info_ptr);
png_uint_32 imgWidth = png_get_image_width(png_ptr, info_ptr);
png_uint_32 imgHeight = png_get_image_height(png_ptr, info_ptr);
png_uint_32 bitdepth = png_get_bit_depth(png_ptr, info_ptr);
png_uint_32 channels = png_get_channels(png_ptr, info_ptr);
png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);
// Convert images to RGB color space
switch (color_type) {
case PNG_COLOR_TYPE_PALETTE:
png_set_palette_to_rgb(png_ptr);
channels = 3;
break;
case PNG_COLOR_TYPE_GRAY:
if (bitdepth < 8) {
png_set_expand_gray_1_2_4_to_8(png_ptr);
}
bitdepth = 8;
break;
}
// Convert transparency (if needed) to a full alpha channel
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_set_tRNS_to_alpha(png_ptr);
channels += 1;
} else if (channels == 3) {
// Add an opaque alpha channel if still none exists
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
channels = 4;
}
// Invert color byte-order as used by plMipmap for DirectX
png_set_bgr(png_ptr);
/// Construct a new mipmap to hold everything
newMipmap = TRACKED_NEW plMipmap(imgWidth, imgHeight, plMipmap::kARGB32Config, 1, plMipmap::kUncompressed);
char* destp = (char*)newMipmap->GetImage();
png_bytep* row_ptrs = TRACKED_NEW png_bytep[imgHeight];
const unsigned int stride = imgWidth * bitdepth * channels / 8;
// Assign row pointers to the appropriate locations in the newly-created Mipmap
for (size_t i = 0; i < imgHeight; i++) {
row_ptrs[i] = (png_bytep)destp + (i * stride);
}
png_read_image(png_ptr, row_ptrs);
png_read_end(png_ptr, end_info);
// Clean up allocated structs
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete [] row_ptrs;
}
} catch (...) {
if (newMipmap != NULL) {
delete newMipmap;
newMipmap = NULL;
}
}
return newMipmap;
}
plMipmap* plPNG::ReadFromFile(const char* fileName)
{
wchar* wFilename = hsStringToWString(fileName);
plMipmap* retVal = ReadFromFile(wFilename);
delete [] wFilename;
return retVal;
}
plMipmap* plPNG::ReadFromFile(const wchar* fileName)
{
hsUNIXStream in;
if (!in.Open(fileName, L"rb")) {
return false;
}
plMipmap* ret = IRead(&in);
in.Close();
return ret;
}
hsBool plPNG::IWrite(plMipmap* source, hsStream* outStream)
{
hsBool result = true;
try {
// Allocate required structs
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
throw(false);
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
throw(false);
}
// Assign delegate function for writing to hsStream
png_set_write_fn(png_ptr, (png_voidp)outStream, pngWriteDelegate, NULL);
UInt8 psize = source->GetPixelSize();
png_set_IHDR(png_ptr, info_ptr, source->GetWidth(), source->GetHeight(), 8, PNG_COLOR_TYPE_RGB_ALPHA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
// Invert color byte-order as used by plMipmap for DirectX
png_set_bgr(png_ptr);
// Write out the image metadata
png_write_info(png_ptr, info_ptr);
char* srcp = (char*)source->GetImage();
png_bytep* row_ptrs = TRACKED_NEW png_bytep[source->GetHeight()];
const unsigned int stride = source->GetWidth() * source->GetPixelSize() / 8;
// Assign row pointers to the appropriate locations in the newly-created Mipmap
for (size_t i = 0; i < source->GetHeight(); i++) {
row_ptrs[i] = (png_bytep)srcp + (i * stride);
}
png_write_image(png_ptr, row_ptrs);
png_write_end(png_ptr, info_ptr);
// Clean up allocated structs
png_destroy_write_struct(&png_ptr, &info_ptr);
delete [] row_ptrs;
} catch (...) {
result = false;
}
return result;
}
hsBool plPNG::WriteToFile(const char* fileName, plMipmap* sourceData)
{
wchar* wFilename = hsStringToWString(fileName);
hsBool retVal = WriteToFile(wFilename, sourceData);
delete [] wFilename;
return retVal;
}
hsBool plPNG::WriteToFile(const wchar* fileName, plMipmap* sourceData)
{
hsUNIXStream out;
if (!out.Open(fileName, L"wb")) {
return false;
}
hsBool ret = IWrite(sourceData, &out);
out.Close();
return ret;
}

View File

@ -0,0 +1,71 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef _plPNG_h
#define _plPNG_h
//// Class Definition /////////////////////////////////////////////////////////
class plMipmap;
class hsStream;
class plPNG {
protected:
plMipmap* IRead(hsStream* inStream);
hsBool IWrite(plMipmap* source, hsStream* outStream);
public:
plMipmap* ReadFromStream(hsStream* inStream) { return IRead(inStream); }
plMipmap* ReadFromFile(const char* fileName);
plMipmap* ReadFromFile(const wchar* fileName);
hsBool WriteToStream(hsStream* outStream, plMipmap* sourceData) { return IWrite(sourceData, outStream); }
hsBool WriteToFile(const char* fileName, plMipmap* sourceData);
hsBool WriteToFile(const wchar* fileName, plMipmap* sourceData);
static plPNG& Instance(void);
};
#endif // _plPNG_h

View File

@ -55,14 +55,11 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plPipeline/plPlates.h"
#include "../plPipeline/plDebugText.h"
#include "../plGImage/plMipmap.h"
#include "hsWindows.h"
#include "../NucleusLib/inc/plPipeline.h"
// base size of the cursor
#define CURSOR_SIZE_X 0.0675f
#define CURSOR_SIZE_Y 0.09f
// The resolution that uses the base size of the cursor.
// All other resolutions will scale the cursor size to keep the same physical size.
#define BASE_WIDTH 1024
@ -447,16 +444,16 @@ void plMouseDevice::SetDisplayResolution(hsScalar Width, hsScalar Height)
IUpdateCursorSize();
}
void plMouseDevice::CreateCursor( int cursor )
void plMouseDevice::CreateCursor( char* cursor )
{
if( fCursor == nil )
{
plPlateManager::Instance().CreatePlate( &fCursor );
fCursor->CreateFromResource( MAKEINTRESOURCE( cursor ) );
fCursor->CreateFromResource(cursor);
}
else
{
fCursor->ReloadFromResource( MAKEINTRESOURCE( cursor ) );
fCursor->ReloadFromResource(cursor);
}
fCursor->SetPosition( 0, 0, 0 );
IUpdateCursorSize();
@ -470,7 +467,7 @@ void plMouseDevice::IUpdateCursorSize()
if(fCursor)
{
// set the size of the cursor based on resolution.
fCursor->SetSize( CURSOR_SIZE_X * BASE_WIDTH / fWidth, CURSOR_SIZE_Y * BASE_HEIGHT / fHeight );
fCursor->SetSize( 2*fCursor->GetMipmap()->GetWidth()/fWidth, 2*fCursor->GetMipmap()->GetHeight()/fHeight );
}
}
@ -557,7 +554,7 @@ void plMouseDevice::ShowCursor(hsBool override)
fInstance->fCursor->SetVisible( true );
}
void plMouseDevice::NewCursor(int cursor)
void plMouseDevice::NewCursor(char* cursor)
{
fInstance->fCursorID = cursor;
fInstance->CreateCursor(cursor);

View File

@ -50,7 +50,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnInputCore/plOSMsg.h"
#include "hsBitVector.h"
#include "hsTemplates.h"
#include "../../apps/plClient/res/resource.h"
class plMessage;
enum plKeyDef;
struct plMouseInfo;
@ -142,27 +141,27 @@ protected:
class plPlate;
#define CURSOR_UP IDB_CURSOR_UP
#define CURSOR_DOWN IDB_CURSOR_DOWN
#define CURSOR_RIGHT IDB_CURSOR_RIGHT
#define CURSOR_LEFT IDB_CURSOR_LEFT
#define CURSOR_OPEN IDB_CURSOR_OPEN
#define CURSOR_GRAB IDB_CURSOR_GRAB
#define CURSOR_CLICKED IDB_CURSOR_CLICKED
#define CURSOR_POISED IDB_CURSOR_POISED
#define CURSOR_ARROW IDB_CURSOR_ARROW
#define CURSOR_4WAY_OPEN IDB_CURSOR_4WAYOPEN
#define CURSOR_4WAY_CLOSED IDB_CURSOR_4WAYCLOSED
#define CURSOR_UPDOWN_CLOSED IDB_CURSOR_UPDOWNCLOSED
#define CURSOR_UPDOWN_OPEN IDB_CURSOR_UPDOWNOPEN
#define CURSOR_LEFTRIGHT_CLOSED IDB_CURSOR_LEFTRIGHTCLOSED
#define CURSOR_LEFTRIGHT_OPEN IDB_CURSOR_LEFTRIGHTOPEN
#define CURSOR_OFFER_BOOK IDB_CURSOR_BOOK
#define CURSOR_OFFER_BOOK_HI IDB_CURSOR_BOOK_HIGHLIGHT
#define CURSOR_OFFER_BOOK_CLICKED IDB_CURSOR_BOOK_CLICKED
#define CURSOR_CLICK_DISABLED IDB_CURSOR_DISABLED
#define CURSOR_HAND IDB_CURSOR_HAND
#define CURSOR_UPWARD IDB_CURSOR_UPWARD
#define CURSOR_UP "cursor_up.png"
#define CURSOR_UPWARD "cursor_upward.png"
#define CURSOR_DOWN "cursor_down.png"
#define CURSOR_RIGHT "cursor_right.png"
#define CURSOR_LEFT "cursor_left.png"
#define CURSOR_OPEN "cursor_open.png"
#define CURSOR_GRAB "cursor_grab.png"
#define CURSOR_CLICKED "cursor_clicked.png"
#define CURSOR_POISED "cursor_poised.png"
#define CURSOR_4WAY_OPEN "cursor_4way_open.png"
#define CURSOR_4WAY_CLOSED "cursor_4way_closed.png"
#define CURSOR_UPDOWN_OPEN "cursor_updown_open.png"
#define CURSOR_UPDOWN_CLOSED "cursor_updown_closed.png"
#define CURSOR_LEFTRIGHT_OPEN "cursor_leftright_open.png"
#define CURSOR_LEFTRIGHT_CLOSED "cursor_leftright_closed.png"
#define CURSOR_OFFER_BOOK "cursor_book.png"
#define CURSOR_OFFER_BOOK_HI "cursor_book_poised.png"
#define CURSOR_OFFER_BOOK_CLICKED "cursor_book_clicked.png"
#define CURSOR_CLICK_DISABLED "cursor_disabled.png"
#define CURSOR_HAND "cursor_up.png"
#define CURSOR_ARROW "cursor_up.png"
class plInputEventMsg;
@ -195,7 +194,7 @@ public:
static void SetMsgAlways(bool b) { plMouseDevice::bMsgAlways = b; }
static void ShowCursor(hsBool override = false);
static void NewCursor(int cursor);
static void NewCursor(char* cursor);
static void HideCursor(hsBool override = false);
static bool GetHideCursor() { return plMouseDevice::bCursorHidden; }
static void SetCursorOpacity( hsScalar opacity = 1.f );
@ -225,11 +224,11 @@ protected:
plPlate *fCursor;
int fCursorID;
char* fCursorID;
static plMouseDevice* fInstance;
static plMouseInfo fDefaultMouseControlMap[];
void CreateCursor( int cursor );
void CreateCursor( char* cursor );
void IUpdateCursorSize();
static bool bMsgAlways;
static bool bCursorHidden;

View File

@ -251,7 +251,7 @@ void plInputInterfaceMgr::ResetClickableState()
void plInputInterfaceMgr::IUpdateCursor( Int32 newCursor )
{
int mouseCursorResID;
char* mouseCursorResID;
fCurrentCursor = newCursor;

View File

@ -56,8 +56,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plDebugText.h"
#include "plPlates.h"
#include "../Apps/plClient/res/resource.h"
#include "hsTimer.h"
@ -86,7 +84,7 @@ void plDTProgressMgr::Activate()
{
plPlateManager::Instance().CreatePlate(&fStaticTextPlate);
fStaticTextPlate->CreateFromJPEGResource(MAKEINTRESOURCE(plProgressMgr::GetStaticTextID(fCurrentStaticText)), 0);
fStaticTextPlate->CreateFromResource(plProgressMgr::GetStaticTextID(fCurrentStaticText));
fStaticTextPlate->SetVisible(true);
fStaticTextPlate->SetOpacity(1.0f);
fStaticTextPlate->SetSize(2 * 0.192f, 2 * 0.041f, true);
@ -97,7 +95,7 @@ void plDTProgressMgr::Activate()
{
plPlateManager::Instance().CreatePlate( &fActivePlate );
fActivePlate->CreateFromJPEGResource( MAKEINTRESOURCE( plProgressMgr::GetLoadingFrameID(fCurrentImage) ), 0 );
fActivePlate->CreateFromResource(plProgressMgr::GetLoadingFrameID(fCurrentImage));
fActivePlate->SetVisible(true);
fActivePlate->SetOpacity(1.0f);
fActivePlate->SetSize(0.6, 0.6, true);
@ -159,7 +157,7 @@ void plDTProgressMgr::Draw( plPipeline *p )
fLastDraw = currentMs;
fActivePlate->ReloadFromJPEGResource(MAKEINTRESOURCE(plProgressMgr::GetInstance()->GetLoadingFrameID(fCurrentImage)), 0);
fActivePlate->ReloadFromResource(plProgressMgr::GetLoadingFrameID(fCurrentImage));
fActivePlate->SetVisible(true);
fActivePlate->SetOpacity(1.0f);
fActivePlate->SetSize(0.6, 0.6, true);

View File

@ -11680,7 +11680,11 @@ void plDXPlateManager::IDrawToDevice( plPipeline *pipe )
fD3DDevice->SetFVF(dxPipe->fSettings.fCurrFVFFormat = PLD3D_PLATEFVF);
fD3DDevice->SetStreamSource( 0, fVertBuffer, 0, sizeof( plPlateVertex ) );
plProfile_Inc(VertexChange);
fD3DDevice->SetTransform( D3DTS_VIEW, &d3dIdentityMatrix );
// To get plates properly pixel-aligned, we need to compensate for D3D9's weird half-pixel
// offset (see http://drilian.com/2008/11/25/understanding-half-pixel-and-half-texel-offsets/
// or http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx).
D3DXMatrixTranslation(&mat, -0.5f/scrnWidthDiv2, -0.5f/scrnHeightDiv2, 0.0f);
fD3DDevice->SetTransform( D3DTS_VIEW, &mat );
oldCullMode = dxPipe->fCurrCullMode;
for( plate = fPlates; plate != nil; plate = plate->GetNext() )

View File

@ -51,6 +51,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plPlates.h"
#include "../plJPEG/plJPEG.h"
#include "../plGImage/plPNG.h"
#include "../plGImage/plMipmap.h"
#include "../plSurface/plLayer.h"
#include "../plSurface/hsGMaterial.h"
@ -59,6 +60,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsGDeviceRef.h"
#include "hsResMgr.h"
#include "plPipeDebugFlags.h"
#include "../plClientResMgr/plClientResMgr.h"
// A bit of a hack so that we will have the correct instance in the SceneViewer
@ -243,302 +245,30 @@ plMipmap *plPlate::CreateMaterial( UInt32 width, UInt32 height, hsBool withAlpha
//// CreateFromResource //////////////////////////////////////////////////////
// Creates a plate's material from a resource of the given name.
// This is where hacks beget hacks.
// We have two problems here. First, the main cursor we use most of the time (IDB_CURSOR_UP)
// is a greyscale cursor, so it's color is copied to alpha and then set to white. But its
// color doesn't go to black, it goes to 0x040404, which when used for alpha is just enough
// to be annoying in 32 bit (ghost white square around cursor).
// Second, Win98 seems to be doing some sort of dither on the cursors that use a color key
// (colorKey == 0xff00ff), so the purple parts aren't exactly matching the colorKey, so
// we have a big opaque (except for the parts that dither out to 0xff00ff) purple square
// around the cursor.
// So, when it comes to color keying, we're going to pretend we're in 16 bit mode, and only
// check the upper 5 bits of each channel. If they match the colorKey, close enough to be
// transparent.
// For grey scale, if the alpha comes out less than 8 (upper 5 bits off), again close enough
// for complete transparency.
//
// All this happens in CreateFromResource and ReloadFromResource, so I've moved the alpha setting
// code to a function they can both use, rather than cut and pasting code (what a concept, must
// be one of those new-fangled OOP patterns).
//
void plPlate::ISetResourceAlphas(UInt32 colorKey)
void plPlate::CreateFromResource(const char *resName)
{
if( !fMipmap )
return;
/// Set alphas
colorKey &= 0x00f8f8f8;
UInt32 numPix = fMipmap->GetWidth() * fMipmap->GetHeight();
UInt32 *d;
int i;
hsBool hasColorKey = false;
for( i = 0, d = (UInt32 *)(fMipmap->GetImage()); i < numPix; i++ )
if (resName)
{
if( (d[ i ] & 0x00f8f8f8) == colorKey )
{
hasColorKey = true;
break;
}
}
if( hasColorKey )
{
for( i = 0, d = (UInt32 *)(fMipmap->GetImage()); i < numPix; i++ )
{
// Win98 for some reason likes to return full alpha on the pixels,
// whereas Win2k/XP likes 0 alpha. Go figure...
if( ( d[ i ] & 0x00f8f8f8 ) == colorKey )
d[ i ] = 0;
else
d[ i ] |= 0xff000000;
}
plMipmap* resTexture = TRACKED_NEW plMipmap;
resTexture->CopyFrom(plClientResMgr::Instance().getResource(resName));
char keyName[128];
sprintf( keyName, "PlateResource#%d", fMagicUniqueKeyInt++ );
hsgResMgr::ResMgr()->NewKey(keyName, resTexture, plLocation::kGlobalFixedLoc);
CreateMaterial(resTexture->GetWidth(), resTexture->GetHeight(), true, resTexture);
}
else
{
// No color key, must be a b/w alpha mask
for( i = 0, d = (UInt32 *)(fMipmap->GetImage()); i < numPix; i++ )
{
UInt32 alpha = d[i] & 0xff;
if( !(alpha & 0xf8) )
d[i] = 0x00ffffff;
else
d[ i ] = ( alpha << 24 ) | 0x00ffffff;
}
// Null resource request - Create a blank Material instead
CreateMaterial(32, 32, true);
}
}
void plPlate::CreateFromResource( const char *resName, UInt32 colorKey )
void plPlate::ReloadFromResource(const char *resName)
{
/*
Someday the following might actually work, once we get a plugin that
exports a material in the latest format, plus have the material actually
read in its layers (or maybe we'll have to read() them in manually?)
Right now, we just keep it here so we don't have to look up how to do it
when we need it.
hsRAMStream rsrcStream;
HGLOBAL rsrcHdl;
HRSRC findInfo;
UInt8 *ptr;
UInt32 size;
findInfo = FindResource( GetModuleHandle( nil ), (LPCTSTR)1001, "HSMR" );
size = SizeofResource( GetModuleHandle( nil ), findInfo );
rsrcHdl = LoadResource( GetModuleHandle( nil ), findInfo );
ptr = (UInt8 *)LockResource( rsrcHdl );
rsrcStream.Write( size, ptr );
UnlockResource( rsrcHdl );
rsrcStream.Rewind();
fMaterial = TRACKED_NEW hsGMaterial;
fMaterial->Read( &rsrcStream );
*/
UInt32 width, height;
#if HS_BUILD_FOR_WIN32
HBITMAP rsrc;
BITMAPINFO bMapInfo;
HDC hDC = GetDC( nil );
rsrc = (HBITMAP)LoadImage( gHInstance, resName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
if( rsrc == nil )
if (resName)
{
/// Copy data into a new material
CreateMaterial( 32, 32, true );
SetSize( 0.1, 0.1 );
ReleaseDC( nil, hDC );
return;
}
// hsAssert( rsrc != nil, "Cannot find specified resource" );
memset( &bMapInfo, 0, sizeof( bMapInfo ) );
bMapInfo.bmiHeader.biSize = sizeof( bMapInfo.bmiHeader );
height = GetDIBits( hDC, rsrc, 0, 0, nil, &bMapInfo, DIB_RGB_COLORS );
hsAssert( height != 0, "Cannot get resource bitmap bits" );
width = bMapInfo.bmiHeader.biWidth;
height = bMapInfo.bmiHeader.biHeight;
bMapInfo.bmiHeader.biBitCount = 32;
bMapInfo.bmiHeader.biCompression = BI_RGB;
#endif
/// Copy data into a new material
CreateMaterial( width, height, true );
SetSize( (float)width, (float)height );
#if HS_BUILD_FOR_WIN32
bMapInfo.bmiHeader.biHeight *= -1;
GetDIBits( hDC, rsrc, 0, height, fMipmap->GetImage(), &bMapInfo, DIB_RGB_COLORS );
ReleaseDC( nil, hDC );
DeleteObject( rsrc );
#endif
ISetResourceAlphas(colorKey);
}
//// ReloadFromResource //////////////////////////////////////////////////////
// Creates a plate's material from a resource of the given name.
void plPlate::ReloadFromResource( const char *resName, UInt32 colorKey )
{
UInt32 width, height;
if( !fMaterial || fMaterial->GetNumLayers() < 1 || fMaterial->GetLayer( 0 ) == nil || fMipmap == nil )
{
hsStatusMessage( "WARNING: Not refilling plate material; bitmap not yet assigned\n" );
return;
}
#if HS_BUILD_FOR_WIN32
HBITMAP rsrc;
BITMAPINFO bMapInfo;
HDC hDC = GetDC( nil );
rsrc = (HBITMAP)LoadImage( gHInstance, resName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
if( rsrc == nil )
{
ReleaseDC( nil, hDC );
return;
}
// hsAssert( rsrc != nil, "Cannot find specified resource" );
memset( &bMapInfo, 0, sizeof( bMapInfo ) );
bMapInfo.bmiHeader.biSize = sizeof( bMapInfo.bmiHeader );
height = GetDIBits( hDC, rsrc, 0, 0, nil, &bMapInfo, DIB_RGB_COLORS );
hsAssert( height != 0, "Cannot get resource bitmap bits" );
width = bMapInfo.bmiHeader.biWidth;
height = bMapInfo.bmiHeader.biHeight;
bMapInfo.bmiHeader.biBitCount = 32;
bMapInfo.bmiHeader.biCompression = BI_RGB;
#endif
/// Copy the data into the existing material
if( fMipmap->GetWidth() != width || fMipmap->GetHeight() != height )
{
hsStatusMessage( "WARNING: Not refilling plate material; resource size does not match\n" );
}
#if HS_BUILD_FOR_WIN32
bMapInfo.bmiHeader.biHeight *= -1;
GetDIBits( hDC, rsrc, 0, height, fMipmap->GetImage(), &bMapInfo, DIB_RGB_COLORS );
ReleaseDC( nil, hDC );
DeleteObject( rsrc );
#endif
ISetResourceAlphas(colorKey);
if( fMipmap->GetDeviceRef() )
fMipmap->GetDeviceRef()->SetDirty( true );
}
void plPlate::CreateFromJPEGResource( const char *resName, UInt32 colorKey )
{
hsRAMStream stream;
plMipmap* jpgTexture = nil;
#if HS_BUILD_FOR_WIN32
HRSRC res = FindResource(NULL, resName, "JPEG");
if (!res)
goto error;
HGLOBAL resourceLoaded = LoadResource(NULL, res);
if (!resourceLoaded)
goto error;
byte* data = (byte*)LockResource(resourceLoaded);
if (!data)
goto error;
DWORD resSize = SizeofResource(NULL, res);
if (resSize == 0)
goto error;
stream.Write(sizeof(DWORD), &resSize);
stream.Write(resSize, data);
stream.Rewind();
UnlockResource(resourceLoaded);
char keyName[128];
sprintf( keyName, "PlateJPEG#%d", fMagicUniqueKeyInt++ );
jpgTexture = plJPEG::Instance().ReadFromStream(&stream);
if (jpgTexture)
{
hsgResMgr::ResMgr()->NewKey(keyName, jpgTexture, plLocation::kGlobalFixedLoc);
#endif
CreateMaterial( 256, 256, true, jpgTexture);
ISetResourceAlphas(colorKey);
return;
}
error:
/// Copy data into a new material
CreateMaterial( 32, 32, true );
SetSize( 0.1, 0.1 );
return;
}
void plPlate::ReloadFromJPEGResource( const char *resName, UInt32 colorKey )
{
hsRAMStream stream;
plMipmap* jpgTexture = nil;
#if HS_BUILD_FOR_WIN32
HRSRC res = FindResource(NULL, resName, "JPEG");
if (!res)
return;
HGLOBAL resourceLoaded = LoadResource(NULL, res);
if (!resourceLoaded)
return;
byte* data = (byte*)LockResource(resourceLoaded);
if (!data)
return;
DWORD resSize = SizeofResource(NULL, res);
if (resSize == 0)
return;
stream.Write(sizeof(DWORD), &resSize);
stream.Write(resSize, data);
stream.Rewind();
UnlockResource(resourceLoaded);
jpgTexture = plJPEG::Instance().ReadFromStream(&stream);
if (jpgTexture)
{
#endif
fMipmap->CopyFrom(jpgTexture);
ISetResourceAlphas(colorKey);
if( fMipmap->GetDeviceRef() )
fMipmap->GetDeviceRef()->SetDirty( true );
delete jpgTexture;
fMipmap->CopyFrom(plClientResMgr::Instance().getResource(resName));
}
}

View File

@ -126,6 +126,7 @@ class plPlate
hsMatrix44 &GetTransform( void ) { return fXformMatrix; }
const char *GetTitle( void ) { return fTitle; }
UInt32 GetFlags( void ) { return fFlags; }
const plMipmap *GetMipmap( void ) { return fMipmap; }
void SetVisible( hsBool vis ) { if( vis ) fFlags |= kFlagVisible; else fFlags &= ~kFlagVisible; }
hsBool IsVisible( void );
@ -142,10 +143,8 @@ class plPlate
void SetSize( hsScalar width, hsScalar height, bool adjustByAspectRatio = false );
plMipmap *CreateMaterial( UInt32 width, UInt32 height, hsBool withAlpha, plMipmap* texture = NULL );
void CreateFromResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void ReloadFromResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void CreateFromJPEGResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void ReloadFromJPEGResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void CreateFromResource( const char *resName );
void ReloadFromResource( const char *resName );
};
//// plGraphPlate Class Definition ///////////////////////////////////////////

View File

@ -55,7 +55,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsTimer.h"
#include "../plPipeline/plPlates.h"
#include "../Apps/plClient/res/resource.h"
#include <string.h>
@ -66,30 +65,14 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
plProgressMgr *plProgressMgr::fManager = nil;
int plProgressMgr::fImageRotation[] = {
IDR_LOADING_01,
IDR_LOADING_18,
IDR_LOADING_17,
IDR_LOADING_16,
IDR_LOADING_15,
IDR_LOADING_14,
IDR_LOADING_13,
IDR_LOADING_12,
IDR_LOADING_11,
IDR_LOADING_10,
IDR_LOADING_09,
IDR_LOADING_08,
IDR_LOADING_07,
IDR_LOADING_06,
IDR_LOADING_05,
IDR_LOADING_04,
IDR_LOADING_03,
IDR_LOADING_02
};
#define LOADING_RES "xLoading_Linking.%02d.png"
#define LOADING_RES_COUNT 18
int plProgressMgr::fStaticTextIDs[] = {
0,
IDR_LOADING_UPDATETEXT,
char* plProgressMgr::fImageRotation[LOADING_RES_COUNT];
char* plProgressMgr::fStaticTextIDs[] = {
"xLoading_Linking_Text.png",
"xLoading_Updating_Text.png"
};
//// Constructor & Destructor ////////////////////////////////////////////////
@ -100,10 +83,23 @@ plProgressMgr::plProgressMgr()
fManager = this;
fCallbackProc = nil;
fCurrentStaticText = kNone;
// Fill array with pre-computed loading frame IDs
for (int i=0; i < LOADING_RES_COUNT; i++)
{
char* frameID = TRACKED_NEW char[128];
sprintf(frameID, LOADING_RES, i);
fImageRotation[i] = frameID;
}
}
plProgressMgr::~plProgressMgr()
{
for (int i=0; i < LOADING_RES_COUNT; i++)
{
delete fImageRotation[i];
}
while( fOperations != nil )
delete fOperations;
fManager = nil;
@ -245,15 +241,15 @@ void plProgressMgr::CancelAllOps( void )
fCurrentStaticText = kNone;
}
int plProgressMgr::GetLoadingFrameID(int index)
char* plProgressMgr::GetLoadingFrameID(int index)
{
if (index < (sizeof(fImageRotation) / sizeof(int)))
if (index < LOADING_RES_COUNT)
return fImageRotation[index];
else
return fImageRotation[0];
}
int plProgressMgr::GetStaticTextID(StaticText staticTextType)
char* plProgressMgr::GetStaticTextID(StaticText staticTextType)
{
return fStaticTextIDs[staticTextType];
}

View File

@ -196,8 +196,8 @@ class plProgressMgr
private:
static plProgressMgr *fManager;
static int fImageRotation[];
static int fStaticTextIDs[];
static char* fImageRotation[];
static char* fStaticTextIDs[];
protected:
@ -229,8 +229,8 @@ class plProgressMgr
virtual ~plProgressMgr();
static plProgressMgr* GetInstance() { return fManager; }
static int GetLoadingFrameID(int index);
static int GetStaticTextID(StaticText staticTextType);
static char* GetLoadingFrameID(int index);
static char* GetStaticTextID(StaticText staticTextType);
virtual void Draw( plPipeline *p ) { }