diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b4c51da..84fc3855 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ find_package(PythonLibs REQUIRED) find_package(EXPAT REQUIRED) find_package(ZLIB REQUIRED) find_package(PhysX REQUIRED) #TODO: Not required if we aren't building the client +find_package(PNG REQUIRED) find_package(Ogg REQUIRED) #TODO: Not required if we aren't building the client find_package(Vorbis REQUIRED) #TODO: Not required if we aren't building the client find_package(Speex REQUIRED) #TODO: Not required if we aren't building the client @@ -86,4 +87,4 @@ endif(MSVC) include_directories(${OPENSSL_INCLUDE_DIR}) add_subdirectory(Sources/Plasma) -add_subdirectory(Sources/Tools) \ No newline at end of file +add_subdirectory(Sources/Tools) diff --git a/Sources/Plasma/Apps/plClient/CMakeLists.txt b/Sources/Plasma/Apps/plClient/CMakeLists.txt index d0bd4802..fd4ccd22 100644 --- a/Sources/Plasma/Apps/plClient/CMakeLists.txt +++ b/Sources/Plasma/Apps/plClient/CMakeLists.txt @@ -15,6 +15,8 @@ include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${PYTHON_INCLUDE_DIR}) include_directories(${CURL_INCLUDE_DIR}) +add_subdirectory(external) + set(plClient_HEADERS plClient.h plClientCreatable.h @@ -40,59 +42,17 @@ set(plClient_TEXT set(plClient_RESOURCES res/plClient.rc res/resource.h - res/banner.bmp - res/bitmap1.bmp - res/bitmap2.bmp - res/bitmap3.bmp - res/bmp00001.bmp - res/bmp00002.bmp - res/bmp00003.bmp - res/bmp00004.bmp - res/bmp00005.bmp - res/book.bmp - res/book_cli.bmp - res/book_hig.bmp res/cnsl1.bin - res/cursor_clicked.bmp - res/cursor_disabled.bmp - res/cursor_down.bmp - res/cursor_grab.bmp - res/cursor_left.bmp - res/cursor_open.bmp - res/cursor_poised.bmp - res/cursor_right.bmp - res/cursor_u.bmp - res/cursor_up.bmp - res/cursor_upward.bmp res/Dirt.ICO res/headspin.ico - res/Microphone.bmp - res/Speaker.bmp - res/xLoading_Linking.01.jpg - res/xLoading_Linking.02.jpg - res/xLoading_Linking.03.jpg - res/xLoading_Linking.04.jpg - res/xLoading_Linking.05.jpg - res/xLoading_Linking.06.jpg - res/xLoading_Linking.07.jpg - res/xLoading_Linking.08.jpg - res/xLoading_Linking.09.jpg - res/xLoading_Linking.10.jpg - res/xLoading_Linking.11.jpg - res/xLoading_Linking.12.jpg - res/xLoading_Linking.13.jpg - res/xLoading_Linking.14.jpg - res/xLoading_Linking.15.jpg - res/xLoading_Linking.16.jpg - res/xLoading_Linking.17.jpg - res/xLoading_Linking.18.jpg - res/xLoading_Linking_Text.jpg - res/xLoading_Updating_Text.jpg ) add_executable(plClient WIN32 ${plClient_SOURCES} ${plClient_HEADERS} ${plClient_TEXT} ${plClient_RESOURCES}) + +add_dependencies(plClient externalResources) + if(PLASMA_EXTERNAL_RELEASE) set_target_properties(plClient PROPERTIES OUTPUT_NAME "UruExplorer") endif(PLASMA_EXTERNAL_RELEASE) @@ -123,6 +83,7 @@ target_link_libraries(plClient plAudible) target_link_libraries(plClient plAudio) target_link_libraries(plClient plAudioCore) target_link_libraries(plClient plAvatar) +target_link_libraries(plClient plClientResMgr) #target_link_libraries(plClient plClientKey) target_link_libraries(plClient plCompression) target_link_libraries(plClient plContainer) @@ -198,6 +159,7 @@ target_link_libraries(plClient ${OPENAL_LIBRARY}) target_link_libraries(plClient ${OPENSSL_LIBRARIES}) target_link_libraries(plClient ${EXPAT_LIBRARY}) target_link_libraries(plClient ${JPEG_LIBRARY}) +target_link_libraries(plClient ${PNG_LIBRARY}) target_link_libraries(plClient ${Speex_LIBRARY}) target_link_libraries(plClient ${PHYSX_LIBRARIES}) target_link_libraries(plClient ${Ogg_LIBRARIES}) diff --git a/Sources/Plasma/Apps/plClient/external/CMakeLists.txt b/Sources/Plasma/Apps/plClient/external/CMakeLists.txt new file mode 100644 index 00000000..7de07535 --- /dev/null +++ b/Sources/Plasma/Apps/plClient/external/CMakeLists.txt @@ -0,0 +1,30 @@ +set(external_SCRIPTS + makeres.py + render_svg.py + create_resource_dat.py +) + +set(external_SOURCES + Cursor_Base.svg + Linking_Book.svg + Loading_Text_rasterfont.svg + Voice_Chat.svg +) + +if(PLASMA_EXTERNAL_RELEASE) + set(Make_Resource_Command + python ${CMAKE_CURRENT_SOURCE_DIR}/makeres.py --optimize --render --package -i ${CMAKE_CURRENT_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}) +else(PLASMA_EXTERNAL_RELEASE) + set(Make_Resource_Command + python ${CMAKE_CURRENT_SOURCE_DIR}/makeres.py --render --package -i ${CMAKE_CURRENT_SOURCE_DIR} -o ${CMAKE_CURRENT_BINARY_DIR}) +endif(PLASMA_EXTERNAL_RELEASE) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resource.dat + COMMAND ${Make_Resource_Command} + DEPENDS ${external_SOURCES} ${external_SCRIPTS} +) +add_custom_target(externalResources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/resource.dat) + +source_group("Source Files" FILES ${external_SOURCES}) +source_group("Script Files" FILES ${external_SCRIPTS}) diff --git a/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg b/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg new file mode 100644 index 00000000..737abfec --- /dev/null +++ b/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Plasma/Apps/plClient/external/Linking_Book.svg b/Sources/Plasma/Apps/plClient/external/Linking_Book.svg new file mode 100644 index 00000000..628b8b55 --- /dev/null +++ b/Sources/Plasma/Apps/plClient/external/Linking_Book.svg @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Plasma/Apps/plClient/external/Loading_Text_rasterfont.svg b/Sources/Plasma/Apps/plClient/external/Loading_Text_rasterfont.svg new file mode 100644 index 00000000..9e9ef2c4 --- /dev/null +++ b/Sources/Plasma/Apps/plClient/external/Loading_Text_rasterfont.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Plasma/Apps/plClient/external/Voice_Chat.svg b/Sources/Plasma/Apps/plClient/external/Voice_Chat.svg new file mode 100644 index 00000000..42ae5ceb --- /dev/null +++ b/Sources/Plasma/Apps/plClient/external/Voice_Chat.svg @@ -0,0 +1,1595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Plasma/Apps/plClient/external/create_resource_dat.py b/Sources/Plasma/Apps/plClient/external/create_resource_dat.py new file mode 100644 index 00000000..50374346 --- /dev/null +++ b/Sources/Plasma/Apps/plClient/external/create_resource_dat.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +from __future__ import print_function +from __future__ import with_statement + +import os +import sys +import glob +import struct +from optparse import OptionParser + +version = 1 + +def create_resource_dat(resfilepath, inrespath): + datHeader = 0xCBBCF00D + datVersion = 0x00000001 + + ## Get list of files to archive + resourceList = glob.glob(os.path.join(inrespath, "*")) + resourceList.sort() + if len(resourceList) == 0: + print("No files found in '{0}'. Quitting.\n".format(inrespath)) + return False + print("{0} resources found in '{1}'.".format(len(resourceList), inrespath, )) + + ## Write each resource into the output file + with open(resfilepath, "wb") as datFile: + datFile.write(struct.pack("SetDataPath("dat"); hsgResMgr::Init(resMgr); + + plClientResMgr::Instance().ILoadResources("resource.dat"); + gClient = TRACKED_NEW plClient; if( gClient == nil ) return false; diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp index d76c3072..9719ca2a 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp @@ -160,6 +160,13 @@ void pyImage::SaveAsJPEG(const wchar* fileName, UInt8 quality) plJPEG::Instance().WriteToFile( fileName, this->GetImage() ); } +#include "plGImage/plPNG.h" +void pyImage::SaveAsPNG(const wchar* fileName) +{ + + plPNG::Instance().WriteToFile( fileName, this->GetImage() ); +} + #include "hsResMgr.h" #include "pnKeyedObject/plUoid.h" PyObject* pyImage::LoadJPEGFromDisk(const wchar* filename, UInt16 width, UInt16 height) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.h b/Sources/Plasma/FeatureLib/pfPython/pyImage.h index d19f7ec0..5c584da6 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.h @@ -150,6 +150,7 @@ public: UInt32 GetWidth(); // returns the width of the image UInt32 GetHeight(); // returns the height of the image void SaveAsJPEG(const wchar* fileName, UInt8 quality = 75); + void SaveAsPNG(const wchar* fileName); static PyObject* LoadJPEGFromDisk(const wchar* filename, UInt16 width, UInt16 height); // returns pyImage #endif }; diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp index bf93fe70..7d5e7a6a 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp @@ -158,6 +158,41 @@ PYTHON_METHOD_DEFINITION(ptImage, saveAsJPEG, args) PYTHON_RETURN_ERROR; } } + +PYTHON_METHOD_DEFINITION(ptImage, saveAsPNG, args) +{ + PyObject* filenameObj; + if (!PyArg_ParseTuple(args, "O", &filenameObj)) + { + PyErr_SetString(PyExc_TypeError, "saveAsPNG expects a string"); + PYTHON_RETURN_ERROR; + } + + if (PyUnicode_Check(filenameObj)) + { + int strLen = PyUnicode_GetSize(filenameObj); + wchar_t* text = TRACKED_NEW wchar_t[strLen + 1]; + PyUnicode_AsWideChar((PyUnicodeObject*)filenameObj, text, strLen); + text[strLen] = L'\0'; + self->fThis->SaveAsPNG(text); + delete [] text; + PYTHON_RETURN_NONE; + } + else if (PyString_Check(filenameObj)) + { + // we'll allow this, just in case something goes weird + char* text = PyString_AsString(filenameObj); + wchar_t* wText = hsStringToWString(text); + self->fThis->SaveAsPNG(wText); + delete [] wText; + PYTHON_RETURN_NONE; + } + else + { + PyErr_SetString(PyExc_TypeError, "saveAsPNG expects a string"); + PYTHON_RETURN_ERROR; + } +} #endif // BUILDING_PYPLASMA PYTHON_START_METHODS_TABLE(ptImage) @@ -167,6 +202,7 @@ PYTHON_START_METHODS_TABLE(ptImage) PYTHON_METHOD_NOARGS(ptImage, getWidth, "Returns the width of the image"), PYTHON_METHOD_NOARGS(ptImage, getHeight, "Returns the height of the image"), PYTHON_METHOD(ptImage, saveAsJPEG, "Params: filename,quality=75\nSaves this image to disk as a JPEG file"), + PYTHON_METHOD(ptImage, saveAsPNG, "Params: filename\nSaves this image to disk as a PNG file"), #endif PYTHON_END_METHODS_TABLE; diff --git a/Sources/Plasma/PubUtilLib/CMakeLists.txt b/Sources/Plasma/PubUtilLib/CMakeLists.txt index b9f942df..7bea08db 100644 --- a/Sources/Plasma/PubUtilLib/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(plAudible) add_subdirectory(plAudio) add_subdirectory(plAudioCore) add_subdirectory(plAvatar) +add_subdirectory(plClientResMgr) add_subdirectory(plCompression) add_subdirectory(plContainer) #add_subdirectory(plDeviceSelector) # Not being used by any current slns diff --git a/Sources/Plasma/PubUtilLib/plAudio/plVoiceChat.cpp b/Sources/Plasma/PubUtilLib/plAudio/plVoiceChat.cpp index 3d5f7d15..c99190ef 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plVoiceChat.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plVoiceChat.cpp @@ -50,8 +50,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 @@ -68,13 +68,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); @@ -192,7 +192,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); @@ -209,7 +209,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); diff --git a/Sources/Plasma/PubUtilLib/plClientResMgr/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plClientResMgr/CMakeLists.txt new file mode 100644 index 00000000..c26d7233 --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plClientResMgr/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories("../../CoreLib") +include_directories("../../NucleusLib/inc") +include_directories("../../NucleusLib") +include_directories("../../PubUtilLib") + +set(plClientResMgr_SOURCES + plClientResMgr.cpp +) + +set(plClientResMgr_HEADERS + plClientResMgr.h +) + +add_library(plClientResMgr STATIC ${plClientResMgr_SOURCES} ${plClientResMgr_HEADERS}) + +source_group("Source Files" FILES ${plClientResMgr_SOURCES}) +source_group("Header Files" FILES ${plClientResMgr_HEADERS}) diff --git a/Sources/Plasma/PubUtilLib/plClientResMgr/plClientResMgr.cpp b/Sources/Plasma/PubUtilLib/plClientResMgr/plClientResMgr.cpp new file mode 100644 index 00000000..2b0b7a0e --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plClientResMgr/plClientResMgr.cpp @@ -0,0 +1,132 @@ +/*==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 . + +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; +} + +plClientResMgr::~plClientResMgr() +{ + if (this->ClientResources) { + std::map::iterator it; + + for (it = this->ClientResources->begin(); it != this->ClientResources->end(); ++it) { + 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() + } + + (*this->ClientResources)[res_name] = res_data; + } + + break; + default: + break; + } + + in.Close(); + } + + delete wFilename; +} + +plMipmap* plClientResMgr::getResource(const char* resname) +{ + plMipmap* resmipmap = NULL; + std::map::iterator it = this->ClientResources->find(resname); + + if (it != this->ClientResources->end()) { + resmipmap = it->second; + } else { + hsAssert(resmipmap, "Unknown client resource requested."); + } + + return resmipmap; +} diff --git a/Sources/Plasma/PubUtilLib/plClientResMgr/plClientResMgr.h b/Sources/Plasma/PubUtilLib/plClientResMgr/plClientResMgr.h new file mode 100644 index 00000000..15e08028 --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plClientResMgr/plClientResMgr.h @@ -0,0 +1,50 @@ +/*==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 . + +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 +#include + +class plMipmap; + +class plClientResMgr { +protected: + std::map* ClientResources; + +public: + plClientResMgr(); + ~plClientResMgr(); + + void ILoadResources(const char* resfile); + + plMipmap* getResource(const char* resname); + + static plClientResMgr& Instance(void); +}; + +#endif // _plClientResMgr_ diff --git a/Sources/Plasma/PubUtilLib/plGImage/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plGImage/CMakeLists.txt index e2baff10..992e5853 100644 --- a/Sources/Plasma/PubUtilLib/plGImage/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plGImage/CMakeLists.txt @@ -3,6 +3,9 @@ include_directories("../../NucleusLib/inc") include_directories("../../NucleusLib") include_directories("../../PubUtilLib") +find_package(PNG REQUIRED) +include_directories(${PNG_INCLUDE_DIR}) + set(plGImage_SOURCES hsCodecManager.cpp hsDXTDirectXCodec.cpp @@ -17,6 +20,7 @@ set(plGImage_SOURCES plFontCache.cpp plLODMipmap.cpp plMipmap.cpp + plPNG.cpp plTGAWriter.cpp plWinFontCache.cpp ) @@ -37,6 +41,7 @@ set(plGImage_HEADERS plGImageCreatable.h plLODMipmap.h plMipmap.h + plPNG.h plTGAWriter.h plWinFontCache.h ) diff --git a/Sources/Plasma/PubUtilLib/plGImage/plPNG.cpp b/Sources/Plasma/PubUtilLib/plGImage/plPNG.cpp new file mode 100644 index 00000000..768a7ef7 --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plGImage/plPNG.cpp @@ -0,0 +1,254 @@ +/*==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 . + +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 +#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; +} diff --git a/Sources/Plasma/PubUtilLib/plGImage/plPNG.h b/Sources/Plasma/PubUtilLib/plGImage/plPNG.h new file mode 100644 index 00000000..f193b639 --- /dev/null +++ b/Sources/Plasma/PubUtilLib/plGImage/plPNG.h @@ -0,0 +1,55 @@ +/*==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 . + +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 diff --git a/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.cpp b/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.cpp index 99bf7c9e..6f467b35 100644 --- a/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.cpp +++ b/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.cpp @@ -296,16 +296,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(); @@ -406,7 +406,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); diff --git a/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.h b/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.h index 3451ce7b..6fffe7bc 100644 --- a/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.h +++ b/Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.h @@ -34,7 +34,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; @@ -118,27 +117,27 @@ public: 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; @@ -171,7 +170,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 ); @@ -201,11 +200,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; diff --git a/Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.cpp b/Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.cpp index f07e81b4..72e85b6f 100644 --- a/Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.cpp @@ -235,7 +235,7 @@ void plInputInterfaceMgr::ResetClickableState() void plInputInterfaceMgr::IUpdateCursor( Int32 newCursor ) { - int mouseCursorResID; + char* mouseCursorResID; fCurrentCursor = newCursor; diff --git a/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp b/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp index d98c3e43..ea0ff3c4 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/plDTProgressMgr.cpp @@ -40,8 +40,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" @@ -70,7 +68,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); @@ -81,7 +79,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); @@ -143,7 +141,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); diff --git a/Sources/Plasma/PubUtilLib/plPipeline/plPlates.cpp b/Sources/Plasma/PubUtilLib/plPipeline/plPlates.cpp index ce596176..1b95d3e1 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/plPlates.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/plPlates.cpp @@ -35,6 +35,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" @@ -43,6 +44,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 @@ -227,302 +229,30 @@ plMipmap *plPlate::CreateMaterial( UInt32 width, UInt32 height, hsBool withAl //// 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( (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; - } - } - 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; - } - } -} - -void plPlate::CreateFromResource( const char *resName, UInt32 colorKey ) -{ -/* - 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 ) - { - /// 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 ) + if (resName) { - ReleaseDC( nil, hDC ); - return; - } - -// hsAssert( rsrc != nil, "Cannot find specified resource" ); + plMipmap* resTexture = TRACKED_NEW plMipmap; + resTexture->CopyFrom(plClientResMgr::Instance().getResource(resName)); - 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" ); + char keyName[128]; + sprintf( keyName, "PlateResource#%d", fMagicUniqueKeyInt++ ); + hsgResMgr::ResMgr()->NewKey(keyName, resTexture, plLocation::kGlobalFixedLoc); + CreateMaterial(resTexture->GetWidth(), resTexture->GetHeight(), true, resTexture); } - -#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) + else { - hsgResMgr::ResMgr()->NewKey(keyName, jpgTexture, plLocation::kGlobalFixedLoc); - -#endif - - CreateMaterial( 256, 256, true, jpgTexture); - ISetResourceAlphas(colorKey); - return; + // Null resource request - Create a blank Material instead + CreateMaterial(32, 32, true); } - -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 ) +void plPlate::ReloadFromResource(const char *resName) { - 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) + if (resName) { - -#endif - fMipmap->CopyFrom(jpgTexture); - - ISetResourceAlphas(colorKey); - - if( fMipmap->GetDeviceRef() ) - fMipmap->GetDeviceRef()->SetDirty( true ); - - delete jpgTexture; + fMipmap->CopyFrom(plClientResMgr::Instance().getResource(resName)); } } diff --git a/Sources/Plasma/PubUtilLib/plPipeline/plPlates.h b/Sources/Plasma/PubUtilLib/plPipeline/plPlates.h index 3e0e64e8..11521445 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/plPlates.h +++ b/Sources/Plasma/PubUtilLib/plPipeline/plPlates.h @@ -127,10 +127,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 /////////////////////////////////////////// diff --git a/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.cpp b/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.cpp index eba00d78..7ba9f65d 100644 --- a/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.cpp +++ b/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.cpp @@ -39,7 +39,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 @@ -50,30 +49,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 + +char* plProgressMgr::fImageRotation[LOADING_RES_COUNT]; -int plProgressMgr::fStaticTextIDs[] = { - 0, - IDR_LOADING_UPDATETEXT, +char* plProgressMgr::fStaticTextIDs[] = { + "xLoading_Linking_Text.png", + "xLoading_Updating_Text.png" }; //// Constructor & Destructor //////////////////////////////////////////////// @@ -84,10 +67,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; @@ -229,15 +225,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]; } diff --git a/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.h b/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.h index 34d526e0..fd9d15a4 100644 --- a/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.h +++ b/Sources/Plasma/PubUtilLib/plProgressMgr/plProgressMgr.h @@ -180,8 +180,8 @@ class plProgressMgr private: static plProgressMgr *fManager; - static int fImageRotation[]; - static int fStaticTextIDs[]; + static char* fImageRotation[]; + static char* fStaticTextIDs[]; protected: @@ -213,8 +213,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 ) { }