diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/config.h.cmake | 18 | ||||
-rw-r--r-- | src/common/event.cpp | 54 | ||||
-rw-r--r-- | src/common/event.h | 290 | ||||
-rw-r--r-- | src/common/image.cpp | 221 | ||||
-rw-r--r-- | src/common/image.h | 84 | ||||
-rw-r--r-- | src/common/iman.cpp | 2 | ||||
-rw-r--r-- | src/common/ioutils.h | 85 | ||||
-rw-r--r-- | src/common/key.h | 34 | ||||
-rw-r--r-- | src/common/logger.cpp | 4 | ||||
-rw-r--r-- | src/common/logger.h | 2 | ||||
-rw-r--r-- | src/common/misc.h | 2 | ||||
-rw-r--r-- | src/common/modfile.cpp | 695 | ||||
-rw-r--r-- | src/common/modfile.h | 115 | ||||
-rw-r--r-- | src/common/singleton.h | 12 | ||||
-rw-r--r-- | src/common/stringutils.cpp | 149 | ||||
-rw-r--r-- | src/common/stringutils.h | 77 | ||||
-rw-r--r-- | src/common/test/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/common/test/image_test.cpp | 34 |
18 files changed, 937 insertions, 947 deletions
diff --git a/src/common/config.h.cmake b/src/common/config.h.cmake index b066387..f496db0 100644 --- a/src/common/config.h.cmake +++ b/src/common/config.h.cmake @@ -1,8 +1,10 @@ -#pragma once
-
-// Macros set by CMake
-#cmakedefine DEBUG
-#cmakedefine PLATFORM_WINDOWS @PLATFORM_WINDOWS@
-#cmakedefine PLATFORM_LINUX @PLATFORM_LINUX@
-#cmakedefine PLATFORM_OTHER @PLATFORM_OTHER@
-
+#pragma once + +// Macros set by CMake +#cmakedefine DEBUG + +#cmakedefine PLATFORM_WINDOWS @PLATFORM_WINDOWS@ +#cmakedefine PLATFORM_LINUX @PLATFORM_LINUX@ +#cmakedefine PLATFORM_OTHER @PLATFORM_OTHER@ + +#cmakedefine USE_GLEW @USE_GLEW@ diff --git a/src/common/event.cpp b/src/common/event.cpp index 9af4691..6a5f4d3 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -16,27 +16,12 @@ // event.cpp -#include "common/iman.h" #include "common/event.h" - -#include <string.h> - - -Event::Event() -{ - event = EVENT_NULL; - param = 0; - axeX = 0.0f; - axeY = 0.0f; - axeZ = 0.0f; - keyState = 0; - rTime = 0.0f; -} +#include "common/iman.h" -// Object's constructor. -CEvent::CEvent(CInstanceManager* iMan) +CEventQueue::CEventQueue(CInstanceManager* iMan) { m_iMan = iMan; m_iMan->AddInstance(CLASS_EVENT, this); @@ -44,51 +29,38 @@ CEvent::CEvent(CInstanceManager* iMan) Flush(); } -// Object's destructor. - -CEvent::~CEvent() +CEventQueue::~CEventQueue() { } - -// Empty the FIFO of events. - -void CEvent::Flush() +void CEventQueue::Flush() { m_head = 0; m_tail = 0; m_total = 0; } -// Produces an event. - -void CEvent::MakeEvent(Event &event, EventMsg msg) -{ - memset(&event, 0, sizeof(Event)); - event.event = msg; -} - -// Adds an event in the FIFO. - -bool CEvent::AddEvent(const Event &event) +/** If the maximum size of queue has been reached, returns \c false. + Else, adds the event to the queue and returns \c true. */ +bool CEventQueue::AddEvent(const Event &event) { - if ( m_total >= MAXEVENT ) return false; + if ( m_total >= MAX_EVENT_QUEUE ) return false; m_fifo[m_head++] = event; - if ( m_head >= MAXEVENT ) m_head = 0; + if ( m_head >= MAX_EVENT_QUEUE ) m_head = 0; m_total ++; return true; } -// Removes an event from the FIFO. - -bool CEvent::GetEvent(Event &event) +/** If the queue is empty, returns \c false. + Else, gets the event from the front, puts it into \a event and returns \c true. */ +bool CEventQueue::GetEvent(Event &event) { if ( m_head == m_tail ) return false; event = m_fifo[m_tail++]; - if ( m_tail >= MAXEVENT ) m_tail = 0; + if ( m_tail >= MAX_EVENT_QUEUE ) m_tail = 0; m_total --; return true; diff --git a/src/common/event.h b/src/common/event.h index 8174fab..0d9aa7c 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -19,40 +19,54 @@ #pragma once +#include "common/key.h" #include "math/point.h" +#include <string.h> -#if !defined (WM_XBUTTONDOWN) -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define XBUTTON1 0x0001 -#define XBUTTON2 0x0002 -#endif +class CInstanceManager; +/** + \enum EventType + \brief Type of event message + */ +enum EventType +{ -class CInstanceManager; +// TODO: document the meaning of each value + //! Invalid event / no event + EVENT_NULL = 0, -const int MAXEVENT = 100; + //! Event sent on user or system quit request + EVENT_QUIT = 1, -// Events. + //? EVENT_FRAME = 2, -enum EventMsg -{ - EVENT_NULL = 0, + //! Event sent after pressing a mouse button + EVENT_MOUSE_BUTTON_DOWN = 3, + //! Event sent after releasing a mouse button + EVENT_MOUSE_BUTTON_UP = 4, + //! Event sent after moving the mouse + EVENT_MOUSE_MOVE = 7, + //! Event sent after pressing a key + EVENT_KEY_DOWN = 8, + //! Event sent after releasing a key + EVENT_KEY_UP = 9, - EVENT_QUIT = 1, - EVENT_FRAME = 2, - EVENT_LBUTTONDOWN = 3, - EVENT_RBUTTONDOWN = 4, - EVENT_LBUTTONUP = 5, - EVENT_RBUTTONUP = 6, - EVENT_MOUSEMOVE = 7, - EVENT_KEYDOWN = 8, - EVENT_KEYUP = 9, - EVENT_CHAR = 10, - EVENT_FOCUS = 11, + //! Event sent when application window loses/gains focus + EVENT_ACTIVE = 10, + + //? EVENT_CHAR = 10, + //? EVENT_FOCUS = 11, + + //! Event sent after moving joystick axes + EVENT_JOY_AXIS = 12, + //! Event sent after pressing a joystick button + EVENT_JOY_BUTTON_DOWN = 13, + //! Event sent after releasing a joystick button + EVENT_JOY_BUTTON_UP = 14, EVENT_UPDINTERFACE = 20, EVENT_WIN = 30, @@ -525,60 +539,168 @@ enum EventMsg EVENT_STUDIO_STEP = 2053, EVENT_USER = 10000, - EVENT_FORCE_DWORD = 0x7fffffff + EVENT_FORCE_LONG = 0x7fffffff +}; + + +/** \enum PressState + \brief State of key/mouse button */ +enum PressState +{ + STATE_PRESSED, + STATE_RELEASED +}; + + +/** \struct KeyEventData + \brief Additional data for keyboard event */ +struct KeyEventData +{ + //! STATE_PRESSED or STATE_RELEASED */ + PressState state; + //! Key symbol: KEY(...) macro value (from common/key.h) + unsigned int key; + //! Keyboard modifiers: a bitmask made of KEY_MOD(...) macro values (from common/key.h) + unsigned int mod; + //! Unicode character + unsigned int unicode; + + KeyEventData() + : state(STATE_PRESSED), key(0), mod(0), unicode(0) {} +}; + +/** \struct MouseMotionEventData + \brief Additional data for mouse move event */ +struct MouseMoveEventData +{ + //! Current button state + unsigned char state; + //! Position of mouse in normalized coordinates (0..1) + Math::Point pos; + + MouseMoveEventData() + : state(STATE_PRESSED) {} +}; + +/** \struct MouseButtonEventData + \brief Additional data mouse button event */ +struct MouseButtonEventData +{ + //! The mouse button index + unsigned char button; + //! STATE_PRESSED or STATE_RELEASED + PressState state; + //! Position of mouse in normalized coordinates (0..1) + Math::Point pos; + + MouseButtonEventData() + : button(0), state(STATE_PRESSED) {} +}; + +/** \struct JoyAxisEventData + \brief Additional data for joystick axis event */ +struct JoyAxisEventData +{ + //! The joystick axis index + unsigned char axis; + //! The axis value (range: -32768 to 32767) + int value; + + JoyAxisEventData() + : axis(axis), value(value) {} +}; + +/** \struct JoyButtonEventData + \brief Additional data for joystick button event */ +struct JoyButtonEventData +{ + //! The joystick button index + unsigned char button; + //! STATE_PRESSED or STATE_RELEASED + PressState state; + + JoyButtonEventData() + : button(0), state(STATE_PRESSED) {} +}; + +/** \enum ActiveEventFlags + \brief Type of focus gained/lost */ +enum ActiveEventFlags +{ + //! Application window focus + ACTIVE_APP = 0x01, + //! Input focus + ACTIVE_INPUT = 0x02, + //! Mouse focus + ACTIVE_MOUSE = 0x04 + +}; + +/** \struct ActiveEventData + \brief Additional data for active event */ +struct ActiveEventData +{ + //! Flags (bitmask of enum values ActiveEventFlags) + unsigned char flags = 0; + //! True if the focus was gained; false otherwise + bool gain; + + ActiveEventData() + : flags(0), gain(false) {} }; + +/** + \struct Event + \brief Event sent by system, interface or game + + Event is described by its type (EventType) and the union + \a data contains additional data about the event. + Different members of the union are filled with different event types. + With some events, nothing is filled (it's zeroed out). + The union contains roughly the same information as SDL_Event struct + but packaged to independent structs and fields. + **/ struct Event { - EventMsg event; // event (EVENT *) - long param; // parameter - Math::Point pos; // mouse position (0 .. 1) - float axeX; // control the X axis (-1 .. 1) - float axeY; // control of the Y axis (-1 .. 1) - float axeZ; // control the Z axis (-1 .. 1) - short keyState; // state of the keyboard (KS_ *) - float rTime; // relative time - - Event(); + //! Type of event (EVENT_*) + EventType type; + + //! If true, the event was produced by system (SDL); else, it has come from user interface + bool systemEvent; + + //! Additional data for EVENT_KEY_DOWN and EVENT_KEY_UP + KeyEventData key; + //! Additional data for EVENT_MOUSE_BUTTON_DOWN and EVENT_MOUSE_BUTTON_UP + MouseButtonEventData mouseButton; + //! Additional data for EVENT_MOUSE_MOVE + MouseMoveEventData mouseMove; + //! Additional data for EVENT_JOY + JoyAxisEventData joyAxis; + //! Additional data for EVENT_JOY_AXIS + JoyButtonEventData joyButton; + //! Additional data for EVENT_ACTIVE + ActiveEventData active; + + //? long param; // parameter + //? Math::Point pos; // mouse position (0 .. 1) + //? float axeX; // control the X axis (-1 .. 1) + //? float axeY; // control of the Y axis (-1 .. 1) + //? float axeZ; // control the Z axis (-1 .. 1) + //? short keyState; // state of the keyboard (KS_ *) + //? float rTime; // relative time + + Event(EventType aType = EVENT_NULL) + : type(aType), systemEvent(false) {} }; -const int VK_BUTTON1 = (0x100+1); // joystick button 1 -const int VK_BUTTON2 = (0x100+2); // joystick button 2 -const int VK_BUTTON3 = (0x100+3); // joystick button 3 -const int VK_BUTTON4 = (0x100+4); // joystick button 4 -const int VK_BUTTON5 = (0x100+5); // joystick button 5 -const int VK_BUTTON6 = (0x100+6); // joystick button 6 -const int VK_BUTTON7 = (0x100+7); // joystick button 7 -const int VK_BUTTON8 = (0x100+8); // joystick button 8 -const int VK_BUTTON9 = (0x100+9); // joystick button 9 -const int VK_BUTTON10 = (0x100+10); // joystick button 10 -const int VK_BUTTON11 = (0x100+11); // joystick button 11 -const int VK_BUTTON12 = (0x100+12); // joystick button 12 -const int VK_BUTTON13 = (0x100+13); // joystick button 13 -const int VK_BUTTON14 = (0x100+14); // joystick button 14 -const int VK_BUTTON15 = (0x100+15); // joystick button 15 -const int VK_BUTTON16 = (0x100+16); // joystick button 16 -const int VK_BUTTON17 = (0x100+17); // joystick button 17 -const int VK_BUTTON18 = (0x100+18); // joystick button 18 -const int VK_BUTTON19 = (0x100+19); // joystick button 19 -const int VK_BUTTON20 = (0x100+20); // joystick button 20 -const int VK_BUTTON21 = (0x100+21); // joystick button 21 -const int VK_BUTTON22 = (0x100+22); // joystick button 22 -const int VK_BUTTON23 = (0x100+23); // joystick button 23 -const int VK_BUTTON24 = (0x100+24); // joystick button 24 -const int VK_BUTTON25 = (0x100+25); // joystick button 25 -const int VK_BUTTON26 = (0x100+26); // joystick button 26 -const int VK_BUTTON27 = (0x100+27); // joystick button 27 -const int VK_BUTTON28 = (0x100+28); // joystick button 28 -const int VK_BUTTON29 = (0x100+29); // joystick button 29 -const int VK_BUTTON30 = (0x100+30); // joystick button 30 -const int VK_BUTTON31 = (0x100+31); // joystick button 31 -const int VK_BUTTON32 = (0x100+32); // joystick button 32 - -const int VK_WHEELUP = (0x200+1); // Mousewheel up -const int VK_WHEELDOWN = (0x200+2); // Mousewheel down +/** + \enum KeyRank + \brief Slots for key assignment of user controls + */ +// TODO: move to global.h ? enum KeyRank { @@ -609,25 +731,37 @@ enum KeyRank }; +/** + \class CEventQueue + \brief Global event queue -class CEvent + Provides an interface to a global FIFO queue with events (both system- and user-generated). + The queue has a fixed maximum size but it should not be a problem. + */ +class CEventQueue { public: - CEvent(CInstanceManager* iMan); - ~CEvent(); + //! Constant maximum size of queue + static const int MAX_EVENT_QUEUE = 100; +public: + //! Object's constructor + CEventQueue(CInstanceManager* iMan); + //! Object's destructor + ~CEventQueue(); + + //! Empties the FIFO of events void Flush(); - void MakeEvent(Event &event, EventMsg msg); + //! Adds an event to the queue bool AddEvent(const Event &event); bool GetEvent(Event &event); protected: CInstanceManager* m_iMan; - - Event m_fifo[MAXEVENT]; - int m_head; - int m_tail; - int m_total; + Event m_fifo[MAX_EVENT_QUEUE]; + int m_head; + int m_tail; + int m_total; }; diff --git a/src/common/image.cpp b/src/common/image.cpp new file mode 100644 index 0000000..3d64377 --- /dev/null +++ b/src/common/image.cpp @@ -0,0 +1,221 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// image.cpp + +#include "image.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <png.h> + + +/* <---------------------------------------------------------------> */ + +/* The following code is from savesurf program by Angelo "Encelo" Theodorou + Source: http://encelo.netsons.org/old/sdl/ + The code was refactored and modified slightly to fit the needs. + The copyright information below is kept unchanged. */ + + +/* SaveSurf: an example on how to save a SDLSurface in PNG + Copyright (C) 2006 Angelo "Encelo" Theodorou + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + NOTE: + + This program is part of "Mars, Land of No Mercy" SDL examples, + you can find other examples on http://marsnomercy.org +*/ + +std::string PNG_ERROR = ""; + +void PNGUserError(png_structp ctx, png_const_charp str) +{ + PNG_ERROR = std::string(str); +} + +int PNGColortypeFromSurface(SDL_Surface *surface) +{ + int colortype = PNG_COLOR_MASK_COLOR; /* grayscale not supported */ + + if (surface->format->palette) + colortype |= PNG_COLOR_MASK_PALETTE; + else if (surface->format->Amask) + colortype |= PNG_COLOR_MASK_ALPHA; + + return colortype; +} + +bool PNGSaveSurface(const char *filename, SDL_Surface *surf) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + int i, colortype; + png_bytep *row_pointers; + + PNG_ERROR = ""; + + /* Opening output file */ + fp = fopen(filename, "wb"); + if (fp == NULL) + { + PNG_ERROR = std::string("Could not open file '") + std::string(filename) + std::string("' for saving"); + return false; + } + + /* Initializing png structures and callbacks */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, PNGUserError, NULL); + if (png_ptr == NULL) + return false; + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + png_destroy_write_struct(&png_ptr, static_cast<png_infopp>(NULL)); + PNG_ERROR = "png_create_info_struct() error!"; + return false; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return false; + } + + png_init_io(png_ptr, fp); + + colortype = PNGColortypeFromSurface(surf); + png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* Writing the image */ + png_write_info(png_ptr, info_ptr); + png_set_packing(png_ptr); + + row_pointers = static_cast<png_bytep*>( malloc(sizeof(png_bytep)*surf->h) ); + for (i = 0; i < surf->h; i++) + row_pointers[i] = static_cast<png_bytep>( static_cast<Uint8 *>(surf->pixels) ) + i*surf->pitch; + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + + /* Cleaning out... */ + free(row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + + return true; +} + +/* <---------------------------------------------------------------> */ + + +CImage::CImage() +{ + m_data = NULL; +} + +CImage::~CImage() +{ + Free(); +} + +bool CImage::IsEmpty() +{ + return m_data == NULL; +} + +void CImage::Free() +{ + if (m_data != NULL) + { + if (m_data->surface != NULL) + { + SDL_FreeSurface(m_data->surface); + m_data->surface = NULL; + } + delete m_data; + m_data = NULL; + } +} + +ImageData* CImage::GetData() +{ + return m_data; +} + +std::string CImage::GetError() +{ + return m_error; +} + +bool CImage::Load(const std::string& fileName) +{ + if (! IsEmpty() ) + Free(); + + m_data = new ImageData(); + + m_error = ""; + + m_data->surface = IMG_Load(fileName.c_str()); + if (m_data->surface == NULL) + { + delete m_data; + m_data = NULL; + + m_error = std::string(IMG_GetError()); + return false; + } + + return true; +} + +bool CImage::SavePNG(const std::string& fileName) +{ + if (IsEmpty()) + { + m_error = "Empty image!"; + return false; + } + + m_error = ""; + + if (! PNGSaveSurface(fileName.c_str(), m_data->surface) ) + { + m_error = PNG_ERROR; + return false; + } + + return true; +} diff --git a/src/common/image.h b/src/common/image.h new file mode 100644 index 0000000..4d86d31 --- /dev/null +++ b/src/common/image.h @@ -0,0 +1,84 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// image.h + +#pragma once + + +#include <stddef.h> +#include <string> + + +// Forward declaration without including headers to clutter the code +struct SDL_Surface; + +//! Implementation-specific image data +/** Note that the struct has no destructor and the surface + will not be freed at destruction. */ +struct ImageData +{ + //! SDL surface with image data + SDL_Surface* surface; + + ImageData() { surface = NULL; } +}; + +/** + \class CImage + \brief Image loaded from file + + Wrapper around SDL_Image library to load images. Also contains + function for saving images to PNG. + */ +class CImage +{ +private: + //! Blocked! + CImage(const CImage &other) {} + //! Blocked! + void operator=(const CImage &other) {} + +public: + //! Constructs empty image (with NULL data) + CImage(); + //! Destroys image, calling Free() + virtual ~CImage(); + + //! Frees the allocated image data + void Free(); + + //! Returns whether the image is empty (has NULL data) + bool IsEmpty(); + + //! Returns the image data; if empty - returns NULL + ImageData* GetData(); + + //! Loads an image from the specified file + bool Load(const std::string &fileName); + + //! Saves the image to the specified file in PNG format + bool SavePNG(const std::string &fileName); + + //! Returns the last error + std::string GetError(); + +private: + //! Last encountered error + std::string m_error; + //! Image data + ImageData* m_data; +}; diff --git a/src/common/iman.cpp b/src/common/iman.cpp index 9e94f24..4c70cde 100644 --- a/src/common/iman.cpp +++ b/src/common/iman.cpp @@ -108,7 +108,7 @@ bool CInstanceManager::AddInstance(ClassType classType, void* pointer, int max) if ( m_table[classType].classPointer == 0 ) { - m_table[classType].classPointer = (void**)malloc(max*sizeof(void*)); + m_table[classType].classPointer = static_cast<void**>( malloc(max*sizeof(void*)) ); m_table[classType].totalPossible = max; m_table[classType].totalUsed = 0; } diff --git a/src/common/ioutils.h b/src/common/ioutils.h new file mode 100644 index 0000000..a7bd044 --- /dev/null +++ b/src/common/ioutils.h @@ -0,0 +1,85 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// ioutils.h + +#pragma once + + +#include <iostream> + +#include <cstring> + +namespace IOUtils { + +//! Writes a binary number to output stream +/** + \c T is a numeric type (int, unsigned int, etc.) + \c N is number of bytes + Write order is little-endian */ +template<int N, typename T> +void WriteBinary(T value, std::ostream &ostr) +{ + for (int i = 0; i < N; ++i) + { + unsigned char byte = (value >> (i*8)) & 0xFF; + ostr.write(reinterpret_cast<char*>(&byte), 1); + } +} + +//! Reads a binary number from input stream +/** + \c T is a numeric type (int, unsigned int, etc.) + \c N is number of bytes + Read order is little-endian */ +template<int N, typename T> +T ReadBinary(std::istream &istr) +{ + T value = 0; + for (int i = 0; i < N; ++i) + { + unsigned char byte = 0; + istr.read(reinterpret_cast<char*>(&byte), 1); + value |= byte << (i*8); + } + return value; +} + +//! Writes a binary 32-bit float to output stream +/** + Write order is little-endian + NOTE: code is probably not portable as there are platforms with other float representations. */ +void WriteBinaryFloat(float value, std::ostream &ostr) +{ + union { float fValue; unsigned int iValue; } u; + memset(&u, 0, sizeof(u)); + u.fValue = value; + IOUtils::WriteBinary<4, unsigned int>(u.iValue, ostr); +} + +//! Reads a binary 32-bit float from input stream +/** + Read order is little-endian + NOTE: code is probably not portable as there are platforms with other float representations. */ +float ReadBinaryFloat(std::istream &istr) +{ + union { float fValue; unsigned int iValue; } u; + memset(&u, 0, sizeof(u)); + u.iValue = IOUtils::ReadBinary<4, unsigned int>(istr); + return u.fValue; +} + +}; // namespace IOUtils diff --git a/src/common/key.h b/src/common/key.h new file mode 100644 index 0000000..de31c09 --- /dev/null +++ b/src/common/key.h @@ -0,0 +1,34 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// key.h + +#pragma once + + +#include "SDL/SDL_keysym.h" + +/* Key definitions are specially defined here so that it is clear in other parts of the code + that these are used. It is to avoid having SDL-related enum values or #defines lying around + unchecked. With this approach it will be easier to maintain the code later on. */ + +// Key symbol defined as concatenation to SDLK_... +// If need arises, it can be changed to custom function or anything else +#define KEY(x) SDLK_ ## x + +// Key modifier defined as concatenation to KMOD_... +// If need arises, it can be changed to custom function or anything else +#define KEY_MOD(x) KMOD_ ## x diff --git a/src/common/logger.cpp b/src/common/logger.cpp index acd1d27..f24726e 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -18,6 +18,8 @@ #include <common/logger.h> +#include <stdio.h> + template<> CLogger* CSingleton<CLogger>::mInstance = 0; @@ -53,7 +55,7 @@ void CLogger::Log(LogType type, const char *str, va_list args) { if (type < mLogLevel) return; - + switch (type) { case LOG_WARN: fprintf(IsOpened() ? mFile : stderr, "[WARN]: "); break; case LOG_INFO: fprintf(IsOpened() ? mFile : stderr, "[INFO]: "); break; diff --git a/src/common/logger.h b/src/common/logger.h index 3a48210..2d0ab3e 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -50,7 +50,7 @@ enum LogType * * @brief Class for loggin information to file or console * -*/ +*/ class CLogger : public CSingleton<CLogger> { public: diff --git a/src/common/misc.h b/src/common/misc.h index e863b69..4853856 100644 --- a/src/common/misc.h +++ b/src/common/misc.h @@ -219,7 +219,7 @@ const int KS_NUMMINUS = (1<<15); // Procedures. -extern EventMsg GetUniqueEventMsg(); +extern EventType GetUniqueEventType(); extern char RetNoAccent(char letter); extern char RetToUpper(char letter); diff --git a/src/common/modfile.cpp b/src/common/modfile.cpp deleted file mode 100644 index fc202b7..0000000 --- a/src/common/modfile.cpp +++ /dev/null @@ -1,695 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * -// * 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/. - -// modfile.cpp - - -#include <windows.h> -#include <stdio.h> -#include <d3d.h> - -#include "common/struct.h" -#include "math/geometry.h" -#include "old/d3dengine.h" -#include "old/d3dmath.h" -#include "common/language.h" -#include "common/event.h" -#include "common/misc.h" -#include "common/iman.h" -#include "old/math3d.h" -#include "common/modfile.h" - - - -const int MAX_VERTICES = 2000; - - - -// Object's constructor. - -CModFile::CModFile(CInstanceManager* iMan) -{ - m_iMan = iMan; - - m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); - - m_triangleUsed = 0; - m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES); - ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES); -} - -// Object's destructor. - -CModFile::~CModFile() -{ - free(m_triangleTable); -} - - - - -// Creates a triangle in the internal structure. - -bool CModFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, - float min, float max) -{ - Math::Vector n; - int i; - - if ( m_triangleUsed >= MAX_VERTICES ) - { - OutputDebugString("ERROR: CreateTriangle::Too many triangles\n"); - return false; - } - - i = m_triangleUsed++; - - ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle)); - - m_triangleTable[i].bUsed = true; - m_triangleTable[i].bSelect = false; - - n = Math::NormalToPlane(p3, p2, p1); - m_triangleTable[i].p1 = D3DVERTEX2( p1, n); - m_triangleTable[i].p2 = D3DVERTEX2( p2, n); - m_triangleTable[i].p3 = D3DVERTEX2( p3, n); - - m_triangleTable[i].material.diffuse.r = 1.0f; - m_triangleTable[i].material.diffuse.g = 1.0f; - m_triangleTable[i].material.diffuse.b = 1.0f; // white - m_triangleTable[i].material.ambient.r = 0.5f; - m_triangleTable[i].material.ambient.g = 0.5f; - m_triangleTable[i].material.ambient.b = 0.5f; - - m_triangleTable[i].min = min; - m_triangleTable[i].max = max; - - return true; -} - -// Reads a DXF file. - -bool CModFile::ReadDXF(char *filename, float min, float max) -{ - FILE* file = NULL; - char line[100]; - int command, rankSommet, nbSommet, nbFace; - Math::Vector table[MAX_VERTICES]; - bool bWaitNbSommet; - bool bWaitNbFace; - bool bWaitSommetX; - bool bWaitSommetY; - bool bWaitSommetZ; - bool bWaitFaceX; - bool bWaitFaceY; - bool bWaitFaceZ; - float x,y,z; - int p1,p2,p3; - - file = fopen(filename, "r"); - if ( file == NULL ) return false; - - m_triangleUsed = 0; - - rankSommet = 0; - bWaitNbSommet = false; - bWaitNbFace = false; - bWaitSommetX = false; - bWaitSommetY = false; - bWaitSommetZ = false; - bWaitFaceX = false; - bWaitFaceY = false; - bWaitFaceZ = false; - - while ( fgets(line, 100, file) != NULL ) - { - sscanf(line, "%d", &command); - if ( fgets(line, 100, file) == NULL ) break; - - if ( command == 66 ) - { - bWaitNbSommet = true; - } - - if ( command == 71 && bWaitNbSommet ) - { - bWaitNbSommet = false; - sscanf(line, "%d", &nbSommet); - if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES; - rankSommet = 0; - bWaitNbFace = true; - -//? sprintf(s, "Waiting for %d sommets\n", nbSommet); -//? OutputDebugString(s); - } - - if ( command == 72 && bWaitNbFace ) - { - bWaitNbFace = false; - sscanf(line, "%d", &nbFace); - bWaitSommetX = true; - -//? sprintf(s, "Waiting for %d faces\n", nbFace); -//? OutputDebugString(s); - } - - if ( command == 10 && bWaitSommetX ) - { - bWaitSommetX = false; - sscanf(line, "%f", &x); - bWaitSommetY = true; - } - - if ( command == 20 && bWaitSommetY ) - { - bWaitSommetY = false; - sscanf(line, "%f", &y); - bWaitSommetZ = true; - } - - if ( command == 30 && bWaitSommetZ ) - { - bWaitSommetZ = false; - sscanf(line, "%f", &z); - - nbSommet --; - if ( nbSommet >= 0 ) - { - Math::Vector p(x,z,y); // permutation of Y and Z! - table[rankSommet++] = p; - bWaitSommetX = true; - -//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z); -//? OutputDebugString(s); - } - else - { - bWaitFaceX = true; - } - } - - if ( command == 71 && bWaitFaceX ) - { - bWaitFaceX = false; - sscanf(line, "%d", &p1); - if ( p1 < 0 ) p1 = -p1; - bWaitFaceY = true; - } - - if ( command == 72 && bWaitFaceY ) - { - bWaitFaceY = false; - sscanf(line, "%d", &p2); - if ( p2 < 0 ) p2 = -p2; - bWaitFaceZ = true; - } - - if ( command == 73 && bWaitFaceZ ) - { - bWaitFaceZ = false; - sscanf(line, "%d", &p3); - if ( p3 < 0 ) p3 = -p3; - - nbFace --; - if ( nbFace >= 0 ) - { - CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max ); - bWaitFaceX = true; - -//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3); -//? OutputDebugString(s); - } - } - - } - - fclose(file); - return true; -} - - - -struct InfoMOD -{ - int rev; - int vers; - int total; - int reserve[10]; -}; - - -// Change nom.bmp to nom.tga - -void ChangeBMPtoTGA(char *filename) -{ - char* p; - - p = strstr(filename, ".bmp"); - if ( p != 0 ) strcpy(p, ".tga"); -} - - -// Reads a MOD file. - -bool CModFile::AddModel(char *filename, int first, bool bEdit, bool bMeta) -{ - FILE* file; - InfoMOD info; - float limit[2]; - int i, nb, err; - char* p; - - if ( m_engine->RetDebugMode() ) - { - bMeta = false; - } - - if ( bMeta ) - { - p = strchr(filename, '\\'); - if ( p == 0 ) - { -#if _SCHOOL - err = g_metafile.Open("ceebot2.dat", filename); -#else - err = g_metafile.Open("colobot2.dat", filename); -#endif - } - else - { -#if _SCHOOL - err = g_metafile.Open("ceebot2.dat", p+1); -#else - err = g_metafile.Open("colobot2.dat", p+1); -#endif - } - if ( err != 0 ) bMeta = false; - } - if ( !bMeta ) - { - file = fopen(filename, "rb"); - if ( file == NULL ) return false; - } - - if ( bMeta ) - { - g_metafile.Read(&info, sizeof(InfoMOD)); - } - else - { - fread(&info, sizeof(InfoMOD), 1, file); - } - nb = info.total; - m_triangleUsed += nb; - - if ( info.rev == 1 && info.vers == 0 ) - { - OldModelTriangle1 old; - - for ( i=first ; i<m_triangleUsed ; i++ ) - { - if ( bMeta ) - { - g_metafile.Read(&old, sizeof(OldModelTriangle1)); - } - else - { - fread(&old, sizeof(OldModelTriangle1), 1, file); - } - - ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle)); - m_triangleTable[i].bUsed = old.bUsed; - m_triangleTable[i].bSelect = old.bSelect; - - m_triangleTable[i].p1.x = old.p1.x; - m_triangleTable[i].p1.y = old.p1.y; - m_triangleTable[i].p1.z = old.p1.z; - m_triangleTable[i].p1.nx = old.p1.nx; - m_triangleTable[i].p1.ny = old.p1.ny; - m_triangleTable[i].p1.nz = old.p1.nz; - m_triangleTable[i].p1.tu = old.p1.tu; - m_triangleTable[i].p1.tv = old.p1.tv; - - m_triangleTable[i].p2.x = old.p2.x; - m_triangleTable[i].p2.y = old.p2.y; - m_triangleTable[i].p2.z = old.p2.z; - m_triangleTable[i].p2.nx = old.p2.nx; - m_triangleTable[i].p2.ny = old.p2.ny; - m_triangleTable[i].p2.nz = old.p2.nz; - m_triangleTable[i].p2.tu = old.p2.tu; - m_triangleTable[i].p2.tv = old.p2.tv; - - m_triangleTable[i].p3.x = old.p3.x; - m_triangleTable[i].p3.y = old.p3.y; - m_triangleTable[i].p3.z = old.p3.z; - m_triangleTable[i].p3.nx = old.p3.nx; - m_triangleTable[i].p3.ny = old.p3.ny; - m_triangleTable[i].p3.nz = old.p3.nz; - m_triangleTable[i].p3.tu = old.p3.tu; - m_triangleTable[i].p3.tv = old.p3.tv; - - m_triangleTable[i].material = old.material; - strcpy(m_triangleTable[i].texName, old.texName); - m_triangleTable[i].min = old.min; - m_triangleTable[i].max = old.max; - } - } - else if ( info.rev == 1 && info.vers == 1 ) - { - OldModelTriangle2 old; - - for ( i=first ; i<m_triangleUsed ; i++ ) - { - if ( bMeta ) - { - g_metafile.Read(&old, sizeof(OldModelTriangle2)); - } - else - { - fread(&old, sizeof(OldModelTriangle2), 1, file); - } - - ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle)); - m_triangleTable[i].bUsed = old.bUsed; - m_triangleTable[i].bSelect = old.bSelect; - - m_triangleTable[i].p1.x = old.p1.x; - m_triangleTable[i].p1.y = old.p1.y; - m_triangleTable[i].p1.z = old.p1.z; - m_triangleTable[i].p1.nx = old.p1.nx; - m_triangleTable[i].p1.ny = old.p1.ny; - m_triangleTable[i].p1.nz = old.p1.nz; - m_triangleTable[i].p1.tu = old.p1.tu; - m_triangleTable[i].p1.tv = old.p1.tv; - - m_triangleTable[i].p2.x = old.p2.x; - m_triangleTable[i].p2.y = old.p2.y; - m_triangleTable[i].p2.z = old.p2.z; - m_triangleTable[i].p2.nx = old.p2.nx; - m_triangleTable[i].p2.ny = old.p2.ny; - m_triangleTable[i].p2.nz = old.p2.nz; - m_triangleTable[i].p2.tu = old.p2.tu; - m_triangleTable[i].p2.tv = old.p2.tv; - - m_triangleTable[i].p3.x = old.p3.x; - m_triangleTable[i].p3.y = old.p3.y; - m_triangleTable[i].p3.z = old.p3.z; - m_triangleTable[i].p3.nx = old.p3.nx; - m_triangleTable[i].p3.ny = old.p3.ny; - m_triangleTable[i].p3.nz = old.p3.nz; - m_triangleTable[i].p3.tu = old.p3.tu; - m_triangleTable[i].p3.tv = old.p3.tv; - - m_triangleTable[i].material = old.material; - strcpy(m_triangleTable[i].texName, old.texName); - m_triangleTable[i].min = old.min; - m_triangleTable[i].max = old.max; - m_triangleTable[i].state = old.state; - m_triangleTable[i].reserve2 = old.reserve2; - m_triangleTable[i].reserve3 = old.reserve3; - m_triangleTable[i].reserve4 = old.reserve4; - } - } - else - { - if ( bMeta ) - { - g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb); - } - else - { - fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file); - } - } - - for ( i=first ; i<m_triangleUsed ; i++ ) - { - ChangeBMPtoTGA(m_triangleTable[i].texName); - } - - if ( !bEdit ) - { - limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config - limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config - - // Standard frontiers -> config. - for ( i=first ; i<m_triangleUsed ; i++ ) - { - if ( m_triangleTable[i].min == 0.0f && - m_triangleTable[i].max == 100.0f ) // resolution A ? - { - m_triangleTable[i].max = limit[0]; - } - else if ( m_triangleTable[i].min == 100.0f && - m_triangleTable[i].max == 200.0f ) // resolution B ? - { - m_triangleTable[i].min = limit[0]; - m_triangleTable[i].max = limit[1]; - } - else if ( m_triangleTable[i].min == 200.0f && - m_triangleTable[i].max == 1000000.0f ) // resolution C ? - { - m_triangleTable[i].min = limit[1]; - } - } - } - - if ( bMeta ) - { - g_metafile.Close(); - } - else - { - fclose(file); - } - return true; -} - -// Reads a MOD file. - -bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta) -{ - m_triangleUsed = 0; - return AddModel(filename, 0, bEdit, bMeta); -} - - -// Writes a MOD file. - -bool CModFile::WriteModel(char *filename) -{ - FILE* file; - InfoMOD info; - - if ( m_triangleUsed == 0 ) return false; - - file = fopen(filename, "wb"); - if ( file == NULL ) return false; - - ZeroMemory(&info, sizeof(InfoMOD)); - info.rev = 1; - info.vers = 2; - info.total = m_triangleUsed; - fwrite(&info, sizeof(InfoMOD), 1, file); - - fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file); - - fclose(file); - return true; -} - - -// Creates the object in the 3D engine. - -bool CModFile::CreateEngineObject(int objRank, int addState) -{ -#if 0 - char texName2[20]; - int texNum, i, state; - - for ( i=0 ; i<m_triangleUsed ; i++ ) - { - if ( !m_triangleTable[i].bUsed ) continue; - - state = m_triangleTable[i].state; - texName2[0] = 0; - - if ( m_triangleTable[i].texNum2 != 0 ) - { - if ( m_triangleTable[i].texNum2 == 1 ) - { - texNum = m_engine->RetSecondTexture(); - } - else - { - texNum = m_triangleTable[i].texNum2; - } - - if ( texNum >= 1 && texNum <= 10 ) - { - state = m_triangleTable[i].state|D3DSTATEDUALb; - } - if ( texNum >= 11 && texNum <= 20 ) - { - state = m_triangleTable[i].state|D3DSTATEDUALw; - } - sprintf(texName2, "dirty%.2d.bmp", texNum); - } - - m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3, - m_triangleTable[i].material, - state+addState, - m_triangleTable[i].texName, texName2, - m_triangleTable[i].min, - m_triangleTable[i].max, false); - } - return true; -#else - char texName1[20]; - char texName2[20]; - int texNum, i, state; - - for ( i=0 ; i<m_triangleUsed ; i++ ) - { - if ( !m_triangleTable[i].bUsed ) continue; - - state = m_triangleTable[i].state; - strcpy(texName1, m_triangleTable[i].texName); - texName2[0] = 0; - - if ( strcmp(texName1, "plant.tga") == 0 ) - { - state |= D3DSTATEALPHA; - } - - if ( m_triangleTable[i].texNum2 != 0 ) - { - if ( m_triangleTable[i].texNum2 == 1 ) - { - texNum = m_engine->RetSecondTexture(); - } - else - { - texNum = m_triangleTable[i].texNum2; - } - - if ( texNum >= 1 && texNum <= 10 ) - { - state |= D3DSTATEDUALb; - } - if ( texNum >= 11 && texNum <= 20 ) - { - state |= D3DSTATEDUALw; - } - sprintf(texName2, "dirty%.2d.tga", texNum); - } - - m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3, - m_triangleTable[i].material, - state+addState, - texName1, texName2, - m_triangleTable[i].min, - m_triangleTable[i].max, false); - } - return true; -#endif -} - - -// Performs a mirror according to Z. - -void CModFile::Mirror() -{ - D3DVERTEX2 t; - int i; - - for ( i=0 ; i<m_triangleUsed ; i++ ) - { - t = m_triangleTable[i].p1; - m_triangleTable[i].p1 = m_triangleTable[i].p2; - m_triangleTable[i].p2 = t; - - m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z; - m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z; - m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z; - - m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz; - m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz; - m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz; - } -} - - -// Returns the pointer to the list of triangles. - -void CModFile::SetTriangleUsed(int total) -{ - m_triangleUsed = total; -} - -int CModFile::RetTriangleUsed() -{ - return m_triangleUsed; -} - -int CModFile::RetTriangleMax() -{ - return MAX_VERTICES; -} - -ModelTriangle* CModFile::RetTriangleList() -{ - return m_triangleTable; -} - - -// Returns the height according to a position (x - z); - -float CModFile::RetHeight(Math::Vector pos) -{ - Math::Vector p1, p2, p3; - float limit; - int i; - - limit = 5.0f; - - for ( i=0 ; i<m_triangleUsed ; i++ ) - { - if ( !m_triangleTable[i].bUsed ) continue; - - if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit && - fabs(pos.z-m_triangleTable[i].p1.z) < limit ) - { - return m_triangleTable[i].p1.y; - } - - if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit && - fabs(pos.z-m_triangleTable[i].p2.z) < limit ) - { - return m_triangleTable[i].p2.y; - } - - if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit && - fabs(pos.z-m_triangleTable[i].p3.z) < limit ) - { - return m_triangleTable[i].p3.y; - } - } - - return 0.0f; -} - - diff --git a/src/common/modfile.h b/src/common/modfile.h deleted file mode 100644 index c852c1e..0000000 --- a/src/common/modfile.h +++ /dev/null @@ -1,115 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * -// * 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/. - -// modfile.h - -#pragma once - - -#include "math/vector.h" -#include "old/d3dengine.h" - - -class CInstanceManager; - - - - -struct OldModelTriangle1 -{ - char bUsed; // true -> using - char bSelect; // true -> selected - D3DVERTEX p1; - D3DVERTEX p2; - D3DVERTEX p3; - D3DMATERIAL7 material; - char texName[20]; - float min; - float max; -}; // length = 196 bytes - -struct OldModelTriangle2 -{ - char bUsed; // true -> used - char bSelect; // true -> selected - D3DVERTEX p1; - D3DVERTEX p2; - D3DVERTEX p3; - D3DMATERIAL7 material; - char texName[20]; - float min; - float max; - long state; - short reserve1; - short reserve2; - short reserve3; - short reserve4; -}; - -struct ModelTriangle -{ - char bUsed; // true -> used - char bSelect; // true -> selected - D3DVERTEX2 p1; - D3DVERTEX2 p2; - D3DVERTEX2 p3; - D3DMATERIAL7 material; - char texName[20]; - float min; - float max; - long state; - short texNum2; - short reserve2; - short reserve3; - short reserve4; -}; // length = 208 bytes - - - - -class CModFile -{ -public: - CModFile(CInstanceManager* iMan); - ~CModFile(); - - bool ReadDXF(char *filename, float min, float max); - bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true); - bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true); - bool WriteModel(char *filename); - - bool CreateEngineObject(int objRank, int addState=0); - void Mirror(); - - void SetTriangleUsed(int total); - int RetTriangleUsed(); - int RetTriangleMax(); - ModelTriangle* RetTriangleList(); - - float RetHeight(Math::Vector pos); - -protected: - bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max); - -protected: - CInstanceManager* m_iMan; - CD3DEngine* m_engine; - - ModelTriangle* m_triangleTable; - int m_triangleUsed; -}; - - diff --git a/src/common/singleton.h b/src/common/singleton.h index dc09645..4df7878 100644 --- a/src/common/singleton.h +++ b/src/common/singleton.h @@ -29,25 +29,25 @@ template<typename T> class CSingleton public: static T& GetInstance() { - aserrt(mInstance); + assert(mInstance != NULL); return *mInstance; } - static T& GetInstancePointer() { - aserrt(mInstance); + static T* GetInstancePointer() { + assert(mInstance != NULL); return mInstance; } static bool IsCreated() { - return mInstance != NULL; + return mInstance != NULL; } CSingleton() { - assert(!mInstance); + assert(mInstance == NULL); mInstance = static_cast<T *>(this); } - ~CSingleton() { + virtual ~CSingleton() { mInstance = NULL; } diff --git a/src/common/stringutils.cpp b/src/common/stringutils.cpp new file mode 100644 index 0000000..585bb46 --- /dev/null +++ b/src/common/stringutils.cpp @@ -0,0 +1,149 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// stringutils.cpp + +#include "stringutils.h" + + +std::string StrUtils::Replace(const std::string &str, const std::string &oldStr, const std::string &newStr) +{ + std::string result = str; + size_t pos = 0; + while ((pos = str.find(oldStr, pos)) != std::string::npos) + { + result.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } + return result; +} + +std::string StrUtils::UnicodeCharToUtf8(unsigned int ch) +{ + std::string result; + if (ch < 0x0080) + { + result += static_cast<char>(ch); + } + else if (ch < 0x0800) + { + char ch1 = 0xC0 | ((ch & 0x07C0) >> 6); + char ch2 = 0x80 | (ch & 0x3F); + result += ch1; + result += ch2; + } + else + { + char ch1 = 0xE0 | ((ch & 0xF000) >> 12); + char ch2 = 0x80 | ((ch & 0x07C0) >> 6); + char ch3 = 0x80 | (ch & 0x3F); + result += ch1; + result += ch2; + result += ch3; + } + return result; +} + +std::string StrUtils::UnicodeStringToUtf8(const std::wstring &str) +{ + std::string result; + for (unsigned int i = 0; i < str.size(); ++i) + result += StrUtils::UnicodeCharToUtf8(static_cast<unsigned int>(str[i])); + + return result; +} + +unsigned int StrUtils::Utf8CharToUnicode(const std::string &ch) +{ + if (ch.empty()) + return 0; + + unsigned int result = 0; + if ((ch[0] & 0x80) == 0) + { + if (ch.size() == 1) + result = static_cast<unsigned int>(ch[0]); + } + else if ((ch[0] & 0xC0) == 0xC0) + { + if (ch.size() == 2) + { + unsigned int ch1 = (ch[0] & 0x1F) << 6; + unsigned int ch2 = (ch[1] & 0x3F); + result = ch1 | ch2; + } + } + else + { + if (ch.size() == 3) + { + unsigned int ch1 = (ch[0] & 0xF0) << 12; + unsigned int ch2 = (ch[1] & 0xC0) << 6; + unsigned int ch3 = (ch[2] & 0xC0); + result = ch1 | ch2 | ch3; + } + } + + return result; +} + +std::wstring StrUtils::Utf8StringToUnicode(const std::string &str) +{ + std::wstring result; + unsigned int pos = 0; + while (pos < str.size()) + { + int len = StrUtils::Utf8CharSizeAt(str, pos); + if (len == 0) + break; + + std::string ch = str.substr(pos, len); + result += static_cast<wchar_t>(StrUtils::Utf8CharToUnicode(ch)); + pos += len; + } + return result; +} + +int StrUtils::Utf8CharSizeAt(const std::string &str, unsigned int pos) +{ + if (pos >= str.size()) + return 0; + + if ((str[pos] & 0x80) == 0) + return 1; + else if ((str[pos] & 0xC0) == 0xC0) + return 2; + else + return 3; + + return 0; +} + +size_t StrUtils::Utf8StringLength(const std::string &str) +{ + size_t result = 0; + for (unsigned int i = 0; i < str.size(); ++i) + { + char ch = str[i]; + if ((ch & 0x80) == 0) + ++result; + else if ((ch & 0xC0) == 0xC0) + result += 2; + else + result += 3; + } + return result; +} diff --git a/src/common/stringutils.h b/src/common/stringutils.h new file mode 100644 index 0000000..a0cae70 --- /dev/null +++ b/src/common/stringutils.h @@ -0,0 +1,77 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * 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/. + +// stringutils.h + +#pragma once + + +#include <string> +#include <sstream> + +namespace StrUtils { + +//! Converts a value to string +/** If given, \a ok is set to true/false on success/failure. + Warning: To avoid unnecessary problems, *always* give full template qualifier e.g. ToString\<int\> */ +template<class T> +std::string ToString(T value, bool *ok = NULL) +{ + std::ostringstream s; + s << value; + if (ok != NULL) + *ok = !s.fail(); + return s.str(); +} + +//! Converts a value to string +/** If given, \a ok is set to true/false on success/failure. + Warning: To avoid unnecessary problems, *always* give full template qualifier e.g. FromString\<int\> */ +template<class T> +T FromString(const std::string &str, bool *ok = NULL) +{ + std::istringstream s; + s.str(str); + T value; + s >> value; + if (ok != NULL) + *ok = !s.fail(); + return value; +} + +//! Returns a string with every occurence of \a oldStr in \a str replaced to \a newStr +std::string Replace(const std::string &str, const std::string &oldStr, const std::string &newStr); + + +//! Converts a wide Unicode char to a single UTF-8 encoded char +std::string UnicodeCharToUtf8(unsigned int ch); + +//! Converts a wide Unicode string to a UTF-8 encoded string +std::string UnicodeStringToUtf8(const std::wstring &str); + +//! Converts a UTF-8 encoded single character to wide Unicode char +unsigned int Utf8CharToUnicode(const std::string &ch); + +//! Converts a UTF-8 encoded string to wide Unicode string +std::wstring Utf8StringToUnicode(const std::string &str); + +//! Returns the size in bytes of UTF-8 character at given \a pos in a UTF-8 \a str +int Utf8CharSizeAt(const std::string &str, unsigned int pos); + +//! Returns the length in characters of UTF-8 string \a str +size_t Utf8StringLength(const std::string &str); + +}; // namespace StrUtil diff --git a/src/common/test/CMakeLists.txt b/src/common/test/CMakeLists.txt new file mode 100644 index 0000000..680116c --- /dev/null +++ b/src/common/test/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 2.8) + +set(CMAKE_BUILD_TYPE debug) +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0") + +add_executable(image_test ../image.cpp image_test.cpp) diff --git a/src/common/test/image_test.cpp b/src/common/test/image_test.cpp new file mode 100644 index 0000000..0ad1ee2 --- /dev/null +++ b/src/common/test/image_test.cpp @@ -0,0 +1,34 @@ +#include "../image.h" + +#include <SDL/SDL.h> +#include <stdio.h> + +/* For now, just a simple test: loading a file from image + * and saving it to another in PNG. */ + +int main(int argc, char *argv[]) +{ + if (argc != 3) + { + printf("Usage: %s in_image out_image\n", argv[0]); + return 0; + } + + CImage image; + + if (! image.Load(argv[1])) + { + std::string err = image.GetError(); + printf("Error loading '%s': %s\n", err.c_str()); + return 1; + } + + if (! image.SavePNG(argv[2])) + { + std::string err = image.GetError(); + printf("Error saving PNG '%s': %s\n", err.c_str()); + return 2; + } + + return 0; +} |