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 @@
+
+
+
+
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 @@
+
+
+
+
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 @@
+
+
+
+
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 @@
+
+
+
+
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