Commit c41fa867 authored by nanahira's avatar nanahira

Merge branch 'master' into regex_minmg

parents 13985af2 a9fb7f42
# data files
/beta
/expansions
/specials
# build files
/bin
/build
/obj
# dependencies
/event
/freetype
/sqlite3
/irrklang
/irrlicht*
# gframe additionals
/gframe/ygopro.ico
/gframe/ygopro.rc
/gframe/ygopro.aps
/gframe/ygopro.icns
/gframe/dirent.h
# git repos
/CustomTools
/DataEditorX
/Magic*
/pics
/Printer
/ygopro-*
/*-Cards
# libs
/*.dll
/*.so
/*.dylib
# windbot related files
/[Bb]ot
/[Bb]ot.conf
/[Bb]ot.exe
/[Bb]ot.sh
/[Ww]ind[Bb]ot
# ygopro config file
/system_user.conf
# ygopro folders
/deck
/fonts
/replay
/single
/screenshots
/sound/*.wav
/sound/custom
/sound/BGM
/update
/update*
/locales
# ygopro main program
/ygopro
/ygopro_*
/ygopro.exe
/ygopro_*.exe
/ygopro.app
/ygopro_*.app
/premake4
/premake4.exe
/premake5
/premake5.exe
# others
*.log
/.vscode
/bak/
/bug.txt
/output
/temp
[Tt]humbs.cdb
/PrinterData.txt
/ygopro_*.bat
/ygopro_*.sh
/*.bat
/*.sh
[submodule "ocgcore"] [submodule "ocgcore"]
path = ocgcore path = ocgcore
url = git@github.com:Fluorohydride/ygopro-core.git url = https://github.com/purerosefallen/ygopro-core.git
[submodule "script"] [submodule "script"]
path = script path = script
url = git@github.com:Fluorohydride/ygopro-scripts.git url = https://github.com/Smile-DK/ygopro-scripts.git
language: cpp
os:
- linux
- osx
sudo: required
dist: xenial
osx_image: xcode8
addons:
ssh_known_hosts:
- github.com
apt:
packages:
- libfreetype6-dev
- libevent-dev
- libsqlite3-dev
- libgl1-mesa-dev
- libglu-dev
- p7zip-full
env:
- USE_IRRKLANG=1
before_install:
- git submodule update --init --recursive
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew update > /dev/null;
brew install freetype libevent sqlite p7zip dylibbundler > /dev/null;
fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
curl --location --retry 5 https://github.com/premake/premake-core/releases/download/v5.0.0-alpha12/premake-5.0.0-alpha12-macosx.tar.gz | tar zfx -;
fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
git clone https://github.com/DailyShana/irrlicht irrlicht_linux;
curl --location --retry 5 https://github.com/premake/premake-core/releases/download/v5.0.0-alpha13/premake-5.0.0-alpha13-linux.tar.gz | tar zfx -;
fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name http://downloads.sourceforge.net/irrlicht/irrlicht-1.8.4.zip; unzip irrlicht-1.8.4.zip ; cd irrlicht-1.8.4/ ; cp ../premake/irrlicht/irrlicht-mac.patch . ; patch -p1 < irrlicht-mac.patch ; cd source/Irrlicht/MacOSX/ ; xcodebuild -project MacOSX.xcodeproj ; cp build/Release/libIrrlicht.a /usr/local/lib/ ; cp -r ../../../include /usr/local/include/irrlicht ; cd ../../../../ ; fi
- git clone --depth=1 https://$NANAHIRA@github.com/purerosefallen/irrklang
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
sudo cp -rf irrklang/bin/macosx-gcc/libirrklang.dylib /usr/local/lib/;
fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
cp -rf irrklang/bin/linux-gcc-64/libIrrKlang.so .;
fi
script:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./premake5 gmake --cc=clang; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./premake5 gmake; fi
- cd build
- make config=release ygopro
- cd ..
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then mv bin/release/ygopro ./; strip ygopro;
fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
mkdir -p ygopro.app/Contents/MacOS;
mv bin/release/ygopro ygopro.app/Contents/MacOS;
dylibbundler -x ygopro.app/Contents/MacOS/ygopro -b -d ygopro.app/Contents/Frameworks/ -p @executable_path/../Frameworks/ -cd;
strip ygopro.app/Contents/MacOS/ygopro; mkdir ygopro.app/Contents/Resources;
mv premake/gframe/ygopro.icns ygopro.app/Contents/Resources/Icon.icns;
defaults write "$PWD/ygopro.app/Contents/Info.plist" "CFBundleIconFile" "Icon.icns";
defaults write "$PWD/ygopro.app/Contents/Info.plist" "CFBundleIdentifier" "moe.mycard.ygopro";
if [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then
echo $CERTIFICATE | base64 --decode --output cert.p12;
security create-keychain -p "" build.keychain; security unlock-keychain -p "" build.keychain;
security import cert.p12 -k build.keychain -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign;
codesign --deep --keychain build.keychain --sign "$(security find-identity -v -p
codesigning build.keychain | head -1 | grep -o '".*"' | tr -d '"')" ygopro.app;
fi
fi
before_deploy:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
7z a -mx9 -xr!.git* KoishiPro-$TRAVIS_OS_NAME-$TRAVIS_TAG.zip ygopro libIrrKlang.so;
fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
7z a -mx9 -xr!.git* KoishiPro-$TRAVIS_OS_NAME-$TRAVIS_TAG.zip ygopro.app;
fi
- curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/HuangYuNan/ygopro222-images/archive/master.zip
- 7z x -y ygopro222-images-master.zip > /dev/null
- mv -f ygopro222-images-master pics
- curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/moecube/ygopro-starter-pack/archive/master.zip
- 7z x -y ygopro-starter-pack-master.zip > /dev/null
- cp -rf ygopro-starter-pack-master/* .
- rm -rf pics/thumbnail pics/*.db
- git clone --depth=1 https://$NANAHIRA@github.com/purerosefallen/fonts
- curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/windbot/releases/download/latest/WindBot.7z
- 7z x -y WindBot.7z > /dev/null
- mv -f WindBot windbot
- curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/windbot/raw/master/BotWrapper/BotWrapper.sh
- mv -f BotWrapper.sh bot
- chmod +x bot
- cd sound
- bash -c "grep '.wav' files.txt | xargs -I {} curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/ygopro-222DIY-data/raw/master/sound/{} ; exit 0"
- cd ..
- git clone --depth=1 https://github.com/purerosefallen/ygopro-database
- mv -f ygopro-database/locales .
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
7z a -mx9 -xr!.git* KoishiPro-$TRAVIS_OS_NAME-full-$TRAVIS_TAG.zip ygopro libIrrKlang.so LICENSE README.md lflist.conf strings.conf system.conf cards.cdb script textures fonts skin deck single pics sound windbot locales bot.conf bot > /dev/null;
fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
7z a -mx9 -xr!.git* KoishiPro-$TRAVIS_OS_NAME-full-$TRAVIS_TAG.zip ygopro.app LICENSE README.md lflist.conf strings.conf system.conf cards.cdb script textures fonts skin deck single pics sound windbot locales bot.conf bot > /dev/null;
fi
deploy:
provider: releases
file:
- KoishiPro-$TRAVIS_OS_NAME-$TRAVIS_TAG.zip
- KoishiPro-$TRAVIS_OS_NAME-full-$TRAVIS_TAG.zip
skip_cleanup: true
overwrite: true
on:
tags: true
api-key: $NANAHIRA
version: '{build}'
image: Visual Studio 2017
environment:
irrklang_pro: 1
access_token:
secure: EQ9miMjfX/QAoBvgc6D+JLmHatLyxOEKZ/uo68QijxWW5Gp4MzB/pOH9+u2GlDVO
install:
- git submodule update --init --recursive
# environment and system dependency
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/premake/premake-core/releases/download/v5.0.0-alpha13/premake-5.0.0-alpha13-windows.zip ; exit 0"
- 7z x -y premake-5.0.0-alpha13-windows.zip
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz ; exit 0"
- tar xf libevent-2.0.22-stable.tar.gz
- move libevent-2.0.22-stable event
- xcopy /E event\WIN32-Code event\include
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name http://downloads.sourceforge.net/freetype/freetype-2.9.1.tar.bz2 ; exit 0"
- tar xf freetype-2.9.1.tar.bz2
- move freetype-2.9.1 freetype
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name http://downloads.sourceforge.net/irrlicht/irrlicht-1.8.4.zip ; exit 0"
- 7z x -y irrlicht-1.8.4.zip
- md irrlicht
- move irrlicht-1.8.4\source\Irrlicht irrlicht\src
- move irrlicht-1.8.4\include irrlicht\include
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://www.sqlite.org/2018/sqlite-amalgamation-3240000.zip ; exit 0"
- 7z x -y sqlite-amalgamation-3240000.zip
- move sqlite-amalgamation-3240000 sqlite3
- git clone --depth=1 https://%access_token%@github.com/purerosefallen/irrklang
# let premake happy
- cp -rf premake/* .
# patch irrlicht & ikpmp3
- patch -p0 < irrlicht\irrlicht.patch
# premake
- premake5 vs2017
configuration: Release
build:
project: build/ygo.sln
parallel: true
after_build:
- mv -f bin/release/ygopro.exe .
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/windbot/releases/download/latest/WindBot.7z ; exit 0"
- 7z x -y WindBot.7z
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/HuangYuNan/ygopro222-images/archive/master.zip ; exit 0"
- 7z x -y ygopro222-images-master.zip
- mv -f ygopro222-images-master pics
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/update-koishipro/archive/master.zip ; exit 0"
- 7z x -y update-koishipro-master.zip
- mv -f update-koishipro-master update-koishipro
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/moecube/ygopro-starter-pack/archive/master.zip ; exit 0"
- 7z x -y ygopro-starter-pack-master.zip
- cp -rf ygopro-starter-pack-master/* .
- cd sound
- bash -c "grep '.wav' files.txt | xargs -I {} curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/ygopro-222DIY-data/raw/master/sound/{} ; exit 0"
- cd ..
- rm -rf pics/thumbnail pics/*.db
- git clone --depth=1 https://github.com/purerosefallen/ygopro-database
- mv -f ygopro-database/locales .
- git clone --depth=1 https://%access_token%@github.com/purerosefallen/fonts
- 7z a -mx9 -xr!.git* KoishiPro-%APPVEYOR_REPO_TAG_NAME%.7z ygopro.exe LICENSE README.md lflist.conf strings.conf system.conf cards.cdb script textures skin deck single pics sound update-koishipro locales fonts WindBot Bot.exe bot.conf
test: off
deploy:
description: 'Automatic build commit $(APPVEYOR_REPO_COMMIT) $(APPVEYOR_REPO_COMMIT_TIMESTAMP)'
provider: GitHub
force_update: true
auth_token: $(access_token)
on:
appveyor_repo_tag: true
artifacts:
- path: ygopro.exe
name: ygopro client
- path: KoishiPro-$(APPVEYOR_REPO_TAG_NAME).7z
name: ygopro full repack
cache:
- premake-5.0.0-alpha13-windows.zip
- libevent-2.0.22-stable.tar.gz
- freetype-2.9.1.tar.bz2
- irrlicht-1.8.4.zip
- sqlite-amalgamation-3240000.zip
File added
#include "CConfigMap.h"
core::stringc CConfigMap::getConfig( const core::stringc& name )
{
core::map<core::stringc,core::stringc>::Node* node = Map.find(name);
if ( node == 0 )
return core::stringc();
return node->getValue();
}
s32 CConfigMap::getConfigAsInt( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return 0;
s32 x = 0;
sscanf( cfg.c_str(), "%d", &x );
return x;
}
f32 CConfigMap::getConfigAsFloat( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return 0;
f32 x = 0.0f;
sscanf( cfg.c_str(), "%f", &x );
return x;
}
core::vector2df CConfigMap::getConfigAsVector2df( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return core::vector2df(0,0);
core::vector2df vec;
sscanf( cfg.c_str(), "%f , %f", &vec.X, &vec.Y );
return vec;
}
core::vector3df CConfigMap::getConfigAsVector3df( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return core::vector3df(0,0,0);
core::vector3df vec;
sscanf( cfg.c_str(), "%f , %f , %f", &vec.X, &vec.Y, &vec.Z );
return vec;
}
bool CConfigMap::hasConfig( const core::stringc& name )
{
core::map<core::stringc,core::stringc>::Node* node = Map.find(name);
return ( node != 0 );
}
void CConfigMap::setConfig( const core::stringc& name, const core::stringc& value )
{
Map.set(name,value);
}
#ifndef CCONFIGMAP_H_
#define CCONFIGMAP_H_
#include <irrMap.h>
#include <irrString.h>
#include <irrTypes.h>
#include <vector2d.h>
#include <vector3d.h>
using namespace irr;
class CConfigMap
{
public:
core::stringc getConfig( const core::stringc& name );
s32 getConfigAsInt( const core::stringc& name );
f32 getConfigAsFloat( const core::stringc& name );
core::vector2df getConfigAsVector2df( const core::stringc& name );
core::vector3df getConfigAsVector3df( const core::stringc& name );
bool hasConfig( const core::stringc& name );
void setConfig( const core::stringc& name, const core::stringc& value );
private:
core::map<core::stringc,core::stringc> Map;
};
#endif
#include "CGUIProgressBar.h"
#include <IGUIEnvironment.h>
#include "CImageGUISkin.h"
#include <IGUIFont.h>
namespace irr
{
namespace gui
{
CGUIProgressBar::CGUIProgressBar( IGUIElement* parent, IGUIEnvironment* environment, const core::rect<s32>& rectangle, s32 id,bool bind )
: IGUIElement( EGUIET_ELEMENT, environment, parent, id, rectangle )
{
FilledRatio = 0.0f;
FillColor = video::SColor(255,255,0,0);
EmptyColor = video::SColor();
AutomaticTextFormat = L"%2.0f %%";
bindColorsToSkin = bind;
}
void CGUIProgressBar::setAutomaticText( const wchar_t* text )
{
AutomaticTextFormat = text? text:L"";
if ( AutomaticTextFormat != L"" )
{
wchar_t* buffer = new wchar_t[ AutomaticTextFormat.size() + 10 ];
swprintf( buffer, AutomaticTextFormat.size() + 10, AutomaticTextFormat.c_str(), 100*FilledRatio );
Text = buffer;
delete buffer;
}
}
void CGUIProgressBar::setFillColor( video::SColor fill )
{
FillColor = fill;
}
video::SColor CGUIProgressBar::getFillColor() const
{
return FillColor;
}
void CGUIProgressBar::setEmptyColor( video::SColor empty )
{
EmptyColor = empty;
}
video::SColor CGUIProgressBar::getEmptyColor() const
{
return EmptyColor;
}
void CGUIProgressBar::setProgress( f32 progress )
{
FilledRatio = progress;
if ( AutomaticTextFormat != L"" )
{
wchar_t* buffer = new wchar_t[ AutomaticTextFormat.size() + 10 ];
swprintf( buffer, AutomaticTextFormat.size() + 10, AutomaticTextFormat.c_str(), 100*FilledRatio );
Text = buffer;
delete buffer;
}
}
f32 CGUIProgressBar::getProgress() const
{
return FilledRatio;
}
void CGUIProgressBar::draw()
{
CImageGUISkin* skin = static_cast<CImageGUISkin*>( Environment->getSkin() );
// Madoc added these changes to let the progress bar get its fill colors from the skin
if(bindColorsToSkin) {
EmptyColor = ((gui::SImageGUISkinConfig)skin->getConfig()).ProgressBar.Color;
FillColor = ((gui::SImageGUISkinConfig)skin->getConfig()).ProgressBarFilled.Color;
}
// End Madoc changes
skin->drawHorizontalProgressBar( this, AbsoluteRect, &AbsoluteClippingRect, FilledRatio, FillColor, EmptyColor );
// Draw text in center
skin->getFont(EGDF_DEFAULT)->draw( Text.c_str(), AbsoluteRect, skin->getColor(EGDC_BUTTON_TEXT), true, true, &AbsoluteClippingRect );
}
}
}
#ifndef CGUIPROGRESSBAR_H_
#define CGUIPROGRESSBAR_H_
#include <IGUIElement.h>
#include <SColor.h>
namespace irr
{
namespace gui
{
/*!
* A horizontal progess bar. ONLY works with CImageGUISkin applied - will fail
* if another skin is used.
*/
class CGUIProgressBar : public IGUIElement
{
public:
// If you want your progress bar colors to be independent of the skin set bind to false -- Madoc
CGUIProgressBar( IGUIElement* parent, IGUIEnvironment* environment, const core::rect<s32>& rectangle, s32 id=-1 ,bool bind=true);
//! Automatically updates the progress bar's text every time the progress changes.
//! Set format to NULL or an empty string to disable automatic text.
void setAutomaticText( const wchar_t* format );
void setFillColor( video::SColor fill );
video::SColor getFillColor() const;
void setEmptyColor( video::SColor empty );
video::SColor getEmptyColor() const;
void setProgress( f32 progress );
f32 getProgress() const;
virtual void draw();
private:
video::SColor FillColor;
video::SColor EmptyColor;
bool bindColorsToSkin;
f32 FilledRatio;
core::stringw AutomaticTextFormat;
};
} // namespace gui
} // namespace irr
#endif
This diff is collapsed.
#ifndef __C_GUISKIN_SYSTEM_H_INCLUDED__
#define __C_GUISKIN_SYSTEM_H_INCLUDED__
#ifdef _WIN32
#include <irrlicht.h>
#endif
#include "CImageGUISkin.h"
#include "CGUIProgressBar.h"
//#include "SkinLoader.h"
#include "../CXMLRegistry/CXMLRegistry.h"
#ifndef _WIN32
// gcc dosnt do 'debug'
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
#define SKINSYSTEM_SKINFILE "/skin.xml"
using namespace irr;
class CGUISkinSystem {
private :
IrrlichtDevice *device;
io::IFileSystem *fs;
io::path skinsPath;
core::array<core::stringw> skinsList;
CXMLRegistry *registry;
gui::CImageGUISkin* loadSkinFromFile(const c8 *skinfile);
void ParseGUIElementStyle(gui::SImageGUIElementStyle& elem, const core::stringc& name,bool nullcolors=false);
bool checkSkinColor(gui::EGUI_DEFAULT_COLOR colToSet,const wchar_t *context,gui::CImageGUISkin *skin);
bool checkSkinSize(gui::EGUI_DEFAULT_SIZE sizeToSet,const wchar_t *context,const wchar_t *key,gui::CImageGUISkin *skin);
bool loadProperty(core::stringw key,gui::CImageGUISkin *skin);
public:
// Constructor
// path = Path to skins
// dev = Irrlicht device
CGUISkinSystem(core::string<wchar_t> path,IrrlichtDevice *dev);
~CGUISkinSystem();
core::array<core::stringw> listSkins();
bool loadSkinList();
bool applySkin(const wchar_t *skinname);
gui::CGUIProgressBar *addProgressBar(gui::IGUIElement *parent,core::rect<s32> rect,bool bindColorsToSkin=true);
// Gets property from current skin
core::stringw getProperty(core::stringw key);
bool populateTreeView(gui::IGUITreeView *control,const core::stringc& skinname);
};
#endif
This diff is collapsed.
#ifndef CIMAGEGUISKIN_H_
#define CIMAGEGUISKIN_H_
#include <IGUISkin.h>
#include <irrString.h>
#include <irrMap.h>
#include <IGUISpriteBank.h>
namespace irr
{
namespace video
{
class IVideoDriver;
class ITexture;
}
namespace gui
{
struct SImageGUIElementStyle
{
struct SBorder
{
s32 Top, Left, Bottom, Right;
SBorder() : Top(0), Left(0), Bottom(0), Right(0) {}
};
SBorder SrcBorder;
SBorder DstBorder;
video::ITexture* Texture;
video::SColor Color;
SImageGUIElementStyle() : Texture(0), Color(255,255,255,255) {}
};
struct SImageGUISkinConfig
{
SImageGUIElementStyle SunkenPane, Window, Button, ButtonPressed, ButtonDisabled, ProgressBar, ProgressBarFilled, TabButton, TabButtonPressed, TabBody, MenuBar, MenuPane, MenuPressed, CheckBox, CheckBoxDisabled, ComboBox, ComboBoxDisabled;
video::SColor CheckBoxColor;
};
class CImageGUISkin : public IGUISkin
{
public:
CImageGUISkin( video::IVideoDriver* videoDriver, IGUISkin* fallbackSkin );
virtual ~CImageGUISkin();
void loadConfig( const SImageGUISkinConfig& config );
//! returns default color
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
//! sets a default color
virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor);
//! returns default color
virtual s32 getSize(EGUI_DEFAULT_SIZE size) const;
//! Returns a default text.
virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const;
//! Sets a default text.
virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText);
//! sets a default size
virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size);
//! returns the default font
virtual IGUIFont* getFont(EGUI_DEFAULT_FONT defaultFont) const;
//! sets a default font
virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT defaultFont);
//! returns the sprite bank
virtual IGUISpriteBank* getSpriteBank() const;
//! sets the sprite bank
virtual void setSpriteBank(IGUISpriteBank* bank);
virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const;
virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index);
virtual void draw3DButtonPaneStandard(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DButtonPanePressed(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DSunkenPane(IGUIElement* element,
video::SColor bgcolor, bool flat, bool fillBackGround,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
/* Updates for irrlicht 1.7 by Mamnarock
virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
*/
virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0,
core::rect<s32>* checkClientArea=0);
virtual void draw3DMenuPane(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DToolBar(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DTabButton(IGUIElement* element, bool active,
const core::rect<s32>& rect, const core::rect<s32>* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT);
virtual void draw3DTabBody(IGUIElement* element, bool border, bool background,
const core::rect<s32>& rect, const core::rect<s32>* clip=0,s32 tabHeight=-1, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT );
virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
const core::position2di position, u32 starttime=0, u32 currenttime=0,
bool loop=false, const core::rect<s32>* clip=0);
// Madoc - I had to add some things
// Exposes config so we can get the progress bar colors
virtual SImageGUISkinConfig getConfig() { return Config; }
// End Madoc adds
virtual void drawHorizontalProgressBar( IGUIElement* element, const core::rect<s32>& rectangle, const core::rect<s32>* clip,
f32 filledRatio, video::SColor fillColor, video::SColor emptyColor );
virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color,
const core::rect<s32>& pos, const core::rect<s32>* clip = 0);
virtual void setProperty(core::stringw key, core::stringw value);
virtual core::stringw getProperty(core::stringw key);
private:
void drawElementStyle( const SImageGUIElementStyle& elem, const core::rect<s32>& rect, const core::rect<s32>* clip, video::SColor* color=0 );
video::IVideoDriver* VideoDriver;
IGUISkin* FallbackSkin;
SImageGUISkinConfig Config;
core::map<core::stringw,core::stringw> properties;
};
}
}
#endif
#ifndef _CLIP_RECTS_H_
#define _CLIP_RECTS_H_
#include <rect.h>
namespace irr
{
//! Workaround for a bug in IVideoDriver::draw2DImage( ITexture* tex, rect<s32> dstRect, rect<s32> srcRect, rect<s32>* clip, SColor* colors, bool alpha )
//! It modifies dstRect and srcRect so the resulting dstRect is entirely inside the clipping rect.
//! srcRect is scaled so the same part of the image is displayed.
//! Returns false if dstRect is entirely outside clip, or true if at least some of it is inside.
inline bool clipRects( core::rect<s32>& dstRect, core::rect<s32>& srcRect, const core::rect<s32>& clip )
{
// Clip left side
if ( dstRect.UpperLeftCorner.X < clip.UpperLeftCorner.X )
{
s32 w = clip.UpperLeftCorner.X - dstRect.UpperLeftCorner.X;
f32 percentRemoved = (f32)w / (f32)dstRect.getWidth();
dstRect.UpperLeftCorner.X = clip.UpperLeftCorner.X;
srcRect.UpperLeftCorner.X += (s32)(percentRemoved * srcRect.getWidth());
}
// Clip top side
if ( dstRect.UpperLeftCorner.Y < clip.UpperLeftCorner.Y )
{
s32 w = clip.UpperLeftCorner.Y - dstRect.UpperLeftCorner.Y;
f32 percentRemoved = (f32)w / (f32)dstRect.getHeight();
dstRect.UpperLeftCorner.Y = clip.UpperLeftCorner.Y;
srcRect.UpperLeftCorner.Y += (s32)(percentRemoved * srcRect.getHeight());
}
// Clip right side
if ( dstRect.LowerRightCorner.X > clip.LowerRightCorner.X )
{
s32 w = dstRect.LowerRightCorner.X - clip.LowerRightCorner.X;
f32 percentRemoved = (f32)w / (f32)dstRect.getWidth();
dstRect.LowerRightCorner.X = clip.LowerRightCorner.X;
srcRect.LowerRightCorner.X -= (s32)(percentRemoved * srcRect.getWidth());
}
// Clip bottom side
if ( dstRect.LowerRightCorner.Y > clip.LowerRightCorner.Y )
{
s32 w = dstRect.LowerRightCorner.Y - clip.LowerRightCorner.Y;
f32 percentRemoved = (f32)w / (f32)dstRect.getHeight();
dstRect.LowerRightCorner.Y = clip.LowerRightCorner.Y;
srcRect.LowerRightCorner.Y -= (s32)(percentRemoved * srcRect.getHeight());
}
return ( dstRect.getWidth() > 0 && dstRect.getHeight() > 0 );
}
} // namespace irr
#endif
#include "CXMLNode.h"
CXMLNODETYPE CXMLNode::getType() { return type; }
void CXMLNode::setType(CXMLNODETYPE newtype) { type = newtype; }
void CXMLNode::setName(const wchar_t* newname) { name = newname; }
const wchar_t* CXMLNode::getName() { return name.c_str(); }
CXMLNode *CXMLNode::getThis() { return this; }
void CXMLNode::setValue(const wchar_t* newvalue) {
value = newvalue;
}
CXMLNode *CXMLNode::getParent() {
return parent;
}
void CXMLNode::setParent(CXMLNode *newparent) {
parent = newparent;
}
/*
bool CXMLNode::getValueAsBool() {
if(!value.size()) return false;
if(value.equals_ignore_case((core::stringw)"true")) return true;
return false;
}
s32 CXMLNode::getValueAsInt() {
if(!value.size()) return 0;
return _wtoi(value.c_str());
}
const wchar_t* CXMLNode::getValueAsCStr() {
if(!value.size()) return false;
return value.c_str();
}
*/
/*
u16 CXMLNode::getChildCount() {
return children.getSize();
}
irr::core::list<CXMLNode*>::Iterator CXMLNode::getFirstChild() {
//if(children.empty()) return 0;
return children.begin();
}
irr::core::list<CXMLNode*>::Iterator CXMLNode::getLastChild() {
//if(children.empty()) return 0;
return children.getLast();
}
*/
const wchar_t* CXMLNode::getValue() {
return value.c_str();
}
void CXMLNode::addChild(CXMLNode *newchild) {
children.push_back(newchild);
}
void CXMLNode::drop() {
if(children.getSize() != 0) {
core::list<CXMLNode*>::Iterator it;
for( it = children.begin(); it != children.end(); it++ ) {
( *it )->drop();
}
children.clear();
}
}
CXMLNode *CXMLNode::findChildByName(const wchar_t *name) {
core::list<CXMLNode*>::Iterator it;
core::stringw tmp;
CXMLNode *node = NULL;
tmp = name;
for( it = children.begin(); it != children.end(); it++ ) {
if(tmp.equals_ignore_case((*it)->getName())) {
node = (*it);
break;
}
}
return node;
}
core::array<const wchar_t*> *CXMLNode::listChildrenByType(CXMLNODETYPE nodetype) {
core::array<const wchar_t*> *ret = new core::array<const wchar_t*>;
//core::stringw construct = L"";
core::list<CXMLNode*>::Iterator it;
for( it = children.begin(); it != children.end(); it++ ) {
if((*it)->getType() == nodetype) {
ret->push_front((*it)->getName());
}
}
return ret;
}
core::array<const wchar_t*> *CXMLNode::listNonNodeChildren() {
return listChildrenByType(CXMLNODETYPE_VALUE);
}
core::array<const wchar_t*> *CXMLNode::listNodeChildren() {
return listChildrenByType(CXMLNODETYPE_NODE);
}
void CXMLNode::populateTreeView(irr::gui::IGUITreeViewNode *node) {
irr::gui::IGUITreeViewNode *myNode;
irr::core::stringw myText;
core::list<CXMLNode*>::Iterator it;
// If I'm a value, I have nothing to add, my parent will do that
if(type == CXMLNODETYPE_VALUE) return;
// So I'm a node, if im not the toplevel node, write me
if(parent != NULL) {
//myText = L"(Key) ";
myText += getName();
myNode = node->addChildBack(myText.c_str());
}
else
myNode = node;
// If I dont have children, I'm done
if(children.empty()) return;
// setup my children
for( it = children.begin(); it != children.end(); it++ ) {
switch((*it)->getType()) {
case CXMLNODETYPE_NODE :
myText = L"";
myText += (core::stringw)(*it)->getName();
(*it)->populateTreeView(myNode);
break;
case CXMLNODETYPE_VALUE :
myText = L"";
myText += (core::stringw)(*it)->getName();
myText += L":";
myText += (core::stringw)(*it)->getValue();
myNode->addChildBack(myText.c_str());
}
}
}
void CXMLNode::writeOut(io::IXMLWriter* xml) {
core::array<core::stringw> names;
core::array<core::stringw> values;
core::list<CXMLNode*>::Iterator it;
bool nodeChildren = false;
// If I'm a value, I have nothing to write, I'll be written by my parent
if(type == CXMLNODETYPE_VALUE) return;
// If I'm a node with no values, which also means no children write as empty and return
if(children.empty()) {
xml->writeElement(name.c_str(),true);
xml->writeLineBreak();
return;
}
// Need to figure out myself first
for( it = children.begin(); it != children.end(); it++ ) {
// cache all my values for writing, and set a flag if I have node children, ie non empty
switch((*it)->getType()) {
case CXMLNODETYPE_VALUE:
names.push_front((core::stringw)(*it)->getName());
values.push_front((core::stringw)(*it)->getValue());
break;
case CXMLNODETYPE_NODE:
nodeChildren = true;
}
}
// At this point I just need to write myself
xml->writeElement(name.c_str(),nodeChildren?false:true,names,values);
xml->writeLineBreak();
// Now I need to see if I have to tell my node children to write
if(!nodeChildren) return;
for( it = children.begin(); it != children.end(); it++ ) {
// If I have a node child, tell it to write, recursion made easy!
if((*it)->getType() == CXMLNODETYPE_NODE) {
(*it)->writeOut(xml);
}
}
xml->writeClosingTag(name.c_str());
xml->writeLineBreak();
}
\ No newline at end of file
// Madoc 05/09
#ifndef __C_XMLNODE_H_INCLUDED__
#define __C_XMLNODE_H_INCLUDED__
#include <irrlicht.h>
using namespace irr;
enum CXMLNODETYPE {
CXMLNODETYPE_VALUE,
CXMLNODETYPE_NODE,
//CXMLNODETYPE_COMMENT
};
class CXMLNode {
public :
/* Decided to move this up to the registry object, reduce mem use.
s32 getValueAsInt();
const wchar_t* getValueAsCStr();
bool getValueAsBool();
*/
CXMLNODETYPE getType();
const wchar_t* getName();
const wchar_t* getValue();
void setType(CXMLNODETYPE newtype);
void setName(const wchar_t* newname);
void setValue(const wchar_t* newvalue);
void addChild(CXMLNode *newchild);
void writeOut(irr::io::IXMLWriter* xml);
void populateTreeView(irr::gui::IGUITreeViewNode *node);
//u16 getChildCount();
void drop();
/*
irr::core::list<CXMLNode*>::Iterator getFirstChild();
// get last is not get end point, this causes problems with iterators
// Screw it, I'll keep all pointers internal
irr::core::list<CXMLNode*>::Iterator getLastChild();
*/
// Careful with these, mem leak waiting to happen
// Maby I should steal IReferenceCounted from irrlicht, would at
// least give me autodetection of mem leaks
core::array<const wchar_t *> *listNonNodeChildren();
core::array<const wchar_t *> *listNodeChildren();
CXMLNode *getThis();
CXMLNode *findChildByName(const wchar_t *name);
CXMLNode *getParent();
void setParent(CXMLNode *newparent);
private :
CXMLNode *parent;
irr::core::stringw value;
irr::core::stringw name;
CXMLNODETYPE type;
irr::core::list<CXMLNode*> children;
irr::core::array<const wchar_t *> *listChildrenByType(CXMLNODETYPE nodetype);
};
#endif
#include "CXMLRegistry.h"
#ifndef _WIN32
inline int _wtoi(const wchar_t * str){
return (int)wcstol(str, 0, 10);
}
#endif
CXMLRegistry::CXMLRegistry(io::IFileSystem *fsys) {
fileSystem = fsys;
fileSystem->grab();
registry = NULL;
}
CXMLRegistry::~CXMLRegistry() {
if(registry != NULL) registry->drop();
fileSystem->drop();
}
bool CXMLRegistry::isTopLevelNode(const wchar_t *node) {
if(registry->findChildByName(node)) return true;
else return false;
}
CXMLNode *CXMLRegistry::resolveContext(const wchar_t* context) {
core::stringw sContext;
CXMLNode *currentNode;
u16 start;
s16 end;
if(!context) return currentContext;
sContext = context;
if(sContext.size() == 0) return 0;
// Make sure the context ends in a /
if(sContext.lastChar() != L'/')
sContext += L'/';
start = 0;
end = sContext.findFirst('/');
// Theres no values in the top level nodes
if(end == -1) return 0;
currentNode = registry;
while(end != -1) {
currentNode = currentNode->findChildByName(sContext.subString(start,end-start).c_str());
if(currentNode == NULL) return NULL;
start = end+1;
end = sContext.findNext('/',start);
}
return currentNode;
}
void CXMLRegistry::setContext(const wchar_t *context) { currentContext = resolveContext(context); }
const wchar_t *CXMLRegistry::convertBoolToText(bool boolval) {
if(boolval) return L"true";
else return L"false";
}
bool CXMLRegistry::convertTextToBool(const wchar_t *textval) {
if(((core::stringw)textval).equals_ignore_case(L"true")) return true;
return false;
}
bool CXMLRegistry::setValue(const wchar_t *index, bool boolval, const wchar_t *context) {
return setValue(index,convertBoolToText(boolval),context);
}
bool CXMLRegistry::setValue(const wchar_t *index, u16 intval, const wchar_t *context) {
return setValue(index,((core::stringw)intval).c_str(),context);
}
bool CXMLRegistry::setValue(const wchar_t *index, const wchar_t * txtval, const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return false;
targetNode = targetNode->findChildByName(index);
if(!targetNode) return false;
targetNode->setValue(txtval);
return true;
}
bool CXMLRegistry::populateTreeView(irr::gui::IGUITreeView *control, const wchar_t *context) {
CXMLNode *targetNode = NULL;
if(context == 0)
targetNode = registry;
else
targetNode = resolveContext(context);
if(!targetNode) return false;
targetNode->populateTreeView(control->getRoot());
return true;
}
bool CXMLRegistry::getValueAsBool(const wchar_t *index, const wchar_t *context) {
return convertTextToBool(getValueAsCStr(index,context));
}
// little more robust
u16 CXMLRegistry::getValueAsInt(const wchar_t *index, const wchar_t *context) {
core::stringw tmp = getValueAsCStr(index,context);
if(tmp.equals_ignore_case("")) return 0;
else return _wtoi(tmp.c_str());
}
core::array<const wchar_t*>* CXMLRegistry::listNonNodeChildren(const wchar_t *node,const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return 0;
return targetNode->listNonNodeChildren();
}
core::array<const wchar_t*>* CXMLRegistry::listNodeChildren(const wchar_t *node,const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return 0;
return targetNode->listNodeChildren();
}
//BROKEN
/*
const irr::c8 *CXMLRegistry::getValueAsCharCStr(const wchar_t *index, const wchar_t *context) {
irr::core::stringc temp;
temp = getValueAsCStr(index,context);
return (const irr::c8 *)temp.c_str();
}
*/
const wchar_t *CXMLRegistry::getValueAsCStr(const wchar_t *index, const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return 0;
targetNode = targetNode->findChildByName(index);
if(!targetNode) return 0;
return targetNode->getValue();
}
irr::core::rect<u32> CXMLRegistry::getValueAsRect(const wchar_t *context) {
CXMLNode *targetNode = resolveContext(context);
irr::u32 tx,ty,bx,by;
if(!targetNode) return irr::core::rect<u32>(0,0,0,0);
tx = _wtoi(targetNode->findChildByName(L"tlx")->getValue());
ty = _wtoi(targetNode->findChildByName(L"tly")->getValue());
bx = _wtoi(targetNode->findChildByName(L"brx")->getValue());
by = _wtoi(targetNode->findChildByName(L"bry")->getValue());
// Hrm what to return on err, cant return null, 0,0,0,0 might be a real loc
// Its u32, maby some HUGE value? maxint?
// Still takes out a value but its less likely
if(!tx || !ty || !bx || !by) return irr::core::rect<u32>(0,0,0,0);
else return irr::core::rect<u32>(tx,ty,bx,by);
}
// Made more robust
irr::video::SColor CXMLRegistry::getValueAsColor(const wchar_t *context) {
CXMLNode *targetNode = resolveContext(context);
if(!targetNode) return NULL;
irr::u32 r,g,b,a;
irr::core::stringw tmp;
tmp = targetNode->findChildByName(L"r")->getValue();
if(tmp.size()) r = _wtoi(tmp.c_str());
tmp = targetNode->findChildByName(L"g")->getValue();
if(tmp.size()) g = _wtoi(tmp.c_str());
tmp = targetNode->findChildByName(L"b")->getValue();
if(tmp.size()) b = _wtoi(tmp.c_str());
tmp = targetNode->findChildByName(L"a")->getValue();
if(tmp.size()) a = _wtoi(tmp.c_str());
return irr::video::SColor(a,r,g,b);
}
bool CXMLRegistry::writeFile(const irr::c8 *fname,const c8 *path) {
io::IXMLWriter* xml;
CXMLNode *currentnode = 0;
core::stringw wstmp;
core::stringc fileName;
wstmp = fname;
currentnode = registry->findChildByName(wstmp.c_str());
if(!currentnode) return false;
fileName = path;
fileName += fname;
fileName += ".xml";
xml = fileSystem->createXMLWriter(fileName.c_str());
xml->writeXMLHeader();
currentnode->writeOut(xml);
// Get rid of double top level end tag
//xml->writeClosingTag(currentnode->getName());
//xml->writeLineBreak();
//if(xml) xml->drop();
delete xml;
return true;
}
// check current folder, if there isnt anything in current, use default
const c8 *CXMLRegistry::resolveConfigPath(const c8 *fname) {
core::string <c8> filename;
bool useCurrent = true;
filename = "config/current/";
filename += fname;
filename += ".xml";
if(!fileSystem->existFile(filename.c_str())) {
useCurrent = false;
}
return useCurrent?"config/current/":"config/defaults/";
}
bool CXMLRegistry::loadConfigFile(const c8 *fname) {
return loadFile(fname, resolveConfigPath(fname));
}
bool CXMLRegistry::writeConfigFile(const c8 *fname) {
return writeFile(fname,"config/current/");
}
// This is tricky, we have to keep track of which nodes are 'open'
bool CXMLRegistry::loadFile(const c8 *fname, const c8 *path) {
io::IXMLReader* xml;
CXMLNode *currentNode = 0;
CXMLNode *topNode = 0;
CXMLNode *currentParent;
core::string <c8> filename;
filename = path;
filename += fname;
// If it dosnt end in .xml add it
if(!filename.subString(filename.size()-4,4).equals_ignore_case(".xml"))
filename += ".xml";
xml = fileSystem->createXMLReader(filename.c_str());
if(!registry) {
registry = new CXMLNode;
registry->setName(L"TopLevelNode");
registry->setType(CXMLNODETYPE_NODE);
}
while(xml && xml->read()) {
CXMLNode *newNode = 0;
switch(xml->getNodeType()) {
case io::EXN_ELEMENT :
u16 i;
newNode = new CXMLNode;
newNode->setName(xml->getNodeName());
newNode->setType(CXMLNODETYPE_NODE);
if(!topNode) {
newNode->setParent(NULL);
registry->addChild(newNode);
topNode = newNode;
currentParent = newNode;
}
else {
newNode->setParent(currentParent);
currentParent->addChild(newNode);
if(!xml->isEmptyElement())
currentParent = newNode;
}
currentNode = newNode;
i = xml->getAttributeCount();
while(i--) {
newNode = new CXMLNode;
newNode->setName(xml->getAttributeName(i));
newNode->setType(CXMLNODETYPE_VALUE);
newNode->setValue(xml->getAttributeValue(i));
currentNode->addChild(newNode);
}
break;
case io::EXN_ELEMENT_END :
// NEVER go back further then the topNode
// Even if the XML is screwed up
if(currentParent->getParent() != NULL)
currentParent = currentParent->getParent();
break;
/*
case io::EXN_COMMENT :
newNode = new CXMLNode;
newNode->setType(CXMLNODETYPE_COMMENT);
//newNode->setValue(xml->getNodeType
currentNode->addChild(newNode);
break;
*/
}
}
//if(xml) xml->drop();
// Documentation says delete not drop
delete xml;
// To support loading multiple files or 'hives' have to
// see if this load ADDED any to decide succcessful or not
if(topNode == 0) return false;
return true;
}
\ No newline at end of file
// Madoc 05/09
#ifndef __C_XMLREGISTRY_H_INCLUDED__
#define __C_XMLREGISTRY_H_INCLUDED__
#include <irrlicht.h>
using namespace irr;
#include "CXMLNode.h"
//File->
// Node1->
// Name1/Value
// Node2->
// Name2/Value
// Oddity: Very little error checking, crashes if you look at it funny
// Oddity: When using setValue ala setValue("someindex",100); compiler cant tell if 100 is a bool or an int, silly compiler,
// casting to u16 works ala setValue("someindex",(u16)100); I see why, but its still silly, and casts are slow
class CXMLRegistry {
public:
CXMLRegistry(io::IFileSystem *fsys);
~CXMLRegistry();
bool loadFile(const c8 *fname, const c8 *path);
bool loadConfigFile(const c8 *fname);
bool writeFile(const c8 *fname, const c8 *path);
bool writeConfigFile(const c8 *fname);
const wchar_t *getValueAsCStr(const wchar_t *index,const wchar_t *context = 0);
// Dosnt work, just declare a stringc and assign the wchar_t to it
//const irr::c8 *getValueAsCharCStr(const wchar_t *index,const wchar_t *context = 0);
bool getValueAsBool(const wchar_t *index, const wchar_t *context = 0);
u16 getValueAsInt(const wchar_t *index, const wchar_t *context = 0);
// This one only takes a context because its going to read 4 childrens values
irr::core::rect<u32> getValueAsRect(const wchar_t *context = 0);
// This one only takes a context because its going to read 4 childrens values
video::SColor getValueAsColor(const wchar_t *context = 0);
irr::core::array<const wchar_t*> *listNonNodeChildren(const wchar_t *node,const wchar_t *context = 0);
irr::core::array<const wchar_t*> *listNodeChildren(const wchar_t *node,const wchar_t *context = 0);
bool setValue(const wchar_t *index, bool boolval, const wchar_t *context = 0);
bool setValue(const wchar_t *index, u16 intval, const wchar_t *context = 0);
bool setValue(const wchar_t *index, const wchar_t *txtval,const wchar_t *context = 0);
// Speed improvement, why search if we want multiple values from the same context
void setContext(const wchar_t *context);
bool isTopLevelNode(const wchar_t *node);
bool populateTreeView(irr::gui::IGUITreeView *control,const wchar_t *context = 0);
// TODO: These are trivial to do, just dont need them yet
// renameNode(context(?),TYPE)
// deleteNode(context(?) (CAREFUL WITH CHILDREN)
// addNode(context, value, type)
// CXMLNODETYPE_COMMENT
// Loading/saving of CDATA, easiest would be just save it in the value of
// the CXMLNODETYPE_NODE their accosicated with.
// make registry inherit node instead of containing an instance of it.
// context(?) might be tricky with CXMLNODETYPE_VALUE
//
//
private:
io::IFileSystem* fileSystem;
CXMLNode* registry;
CXMLNode* currentContext;
const wchar_t *convertBoolToText(bool boolval);
bool convertTextToBool(const wchar_t* textval);
CXMLNode *resolveContext(const wchar_t* context);
const irr::c8 *resolveConfigPath(const irr::c8 *fname);
};
#endif
This diff is collapsed.
...@@ -31,6 +31,7 @@ public: ...@@ -31,6 +31,7 @@ public:
std::vector<ClientCard*> grave[2]; std::vector<ClientCard*> grave[2];
std::vector<ClientCard*> remove[2]; std::vector<ClientCard*> remove[2];
std::vector<ClientCard*> extra[2]; std::vector<ClientCard*> extra[2];
std::vector<ClientCard*> limbo_temp;
std::set<ClientCard*> overlay_cards; std::set<ClientCard*> overlay_cards;
std::vector<ClientCard*> summonable_cards; std::vector<ClientCard*> summonable_cards;
std::vector<ClientCard*> spsummonable_cards; std::vector<ClientCard*> spsummonable_cards;
...@@ -116,6 +117,8 @@ public: ...@@ -116,6 +117,8 @@ public:
void UpdateDeclarableCodeOpcode(bool enter); void UpdateDeclarableCodeOpcode(bool enter);
void UpdateDeclarableCode(bool enter); void UpdateDeclarableCode(bool enter);
void RefreshCardCountDisplay();
irr::gui::IGUIElement* panel; irr::gui::IGUIElement* panel;
std::vector<int> ancard; std::vector<int> ancard;
int hovered_controler; int hovered_controler;
......
...@@ -56,8 +56,13 @@ inline int myswprintf(wchar_t(&buf)[N], const wchar_t* fmt, TR... args) { ...@@ -56,8 +56,13 @@ inline int myswprintf(wchar_t(&buf)[N], const wchar_t* fmt, TR... args) {
} }
#include <irrlicht.h> #include <irrlicht.h>
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
#endif
#include "CGUITTFont.h" #include "CGUITTFont.h"
#include "CGUIImageButton.h" #include "CGUIImageButton.h"
#include <iostream> #include <iostream>
...@@ -80,7 +85,7 @@ using namespace video; ...@@ -80,7 +85,7 @@ using namespace video;
using namespace io; using namespace io;
using namespace gui; using namespace gui;
extern const unsigned short PRO_VERSION; extern unsigned short PRO_VERSION;
extern int enable_log; extern int enable_log;
extern bool exit_on_return; extern bool exit_on_return;
extern bool open_file; extern bool open_file;
......
...@@ -66,7 +66,13 @@ bool DataManager::LoadDB(const char* file) { ...@@ -66,7 +66,13 @@ bool DataManager::LoadDB(const char* file) {
return true; return true;
} }
bool DataManager::LoadStrings(const char* file) { bool DataManager::LoadStrings(const char* file) {
#ifdef _WIN32
wchar_t fname[1024];
BufferIO::DecodeUTF8(file, fname);
FILE* fp = _wfopen(fname, L"r");
#else
FILE* fp = fopen(file, "r"); FILE* fp = fopen(file, "r");
#endif // _WIN32
if(!fp) if(!fp)
return false; return false;
char linebuf[256]; char linebuf[256];
......
...@@ -104,6 +104,7 @@ void DeckBuilder::Terminate() { ...@@ -104,6 +104,7 @@ void DeckBuilder::Terminate() {
mainGame->device->setEventReceiver(&mainGame->menuHandler); mainGame->device->setEventReceiver(&mainGame->menuHandler);
mainGame->wACMessage->setVisible(false); mainGame->wACMessage->setVisible(false);
mainGame->ClearTextures(); mainGame->ClearTextures();
mainGame->showingcode = 0;
mainGame->scrFilter->setVisible(false); mainGame->scrFilter->setVisible(false);
int sel = mainGame->cbDBDecks->getSelected(); int sel = mainGame->cbDBDecks->getSelected();
if(sel >= 0) if(sel >= 0)
...@@ -129,7 +130,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -129,7 +130,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
switch(id) { switch(id) {
case BUTTON_CLEAR_DECK: { case BUTTON_CLEAR_DECK: {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->textFont, dataManager.GetSysString(1339)); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, dataManager.GetSysString(1339));
mainGame->PopupElement(mainGame->wQuery); mainGame->PopupElement(mainGame->wQuery);
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
prev_operation = id; prev_operation = id;
...@@ -178,6 +179,46 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -178,6 +179,46 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
} }
break; break;
} }
case BUTTON_RENAME_DECK: {
int sel = mainGame->cbDBDecks->getSelected();
if(sel == -1)
break;
mainGame->gMutex.Lock();
mainGame->wRenameDeck->setText(dataManager.GetSysString(1376));
mainGame->ebREName->setText(mainGame->cbDBDecks->getItem(sel));
mainGame->PopupElement(mainGame->wRenameDeck);
mainGame->gMutex.Unlock();
prev_operation = id;
prev_sel = sel;
break;
}
case BUTTON_RENAME_DECK_SAVE: {
mainGame->HideElement(mainGame->wRenameDeck);
if(prev_operation == BUTTON_RENAME_DECK) {
wchar_t newname[256];
BufferIO::CopyWStr(mainGame->ebREName->getText(), newname, 256);
if(mywcsncasecmp(newname + wcslen(newname) - 4, L"", 4)) {
myswprintf(newname, L"%ls", mainGame->ebREName->getText());
}
if(DeckManager::RenameDeck(mainGame->cbDBDecks->getItem(prev_sel), newname)) {
mainGame->RefreshDeck(mainGame->cbDBDecks);
mainGame->cbDBDecks->setSelected(prev_sel);
mainGame->stACMessage->setText(dataManager.GetSysString(1375));
mainGame->PopupElement(mainGame->wACMessage, 20);
} else {
mainGame->env->addMessageBox(L"", dataManager.GetSysString(1365));
}
}
prev_operation = 0;
prev_sel = -1;
break;
}
case BUTTON_RENAME_DECK_CANCEL: {
mainGame->HideElement(mainGame->wRenameDeck);
prev_operation = 0;
prev_sel = -1;
break;
}
case BUTTON_DELETE_DECK: { case BUTTON_DELETE_DECK: {
int sel = mainGame->cbDBDecks->getSelected(); int sel = mainGame->cbDBDecks->getSelected();
if(sel == -1) if(sel == -1)
...@@ -185,7 +226,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -185,7 +226,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
wchar_t textBuffer[256]; wchar_t textBuffer[256];
myswprintf(textBuffer, L"%ls\n%ls", mainGame->cbDBDecks->getItem(sel), dataManager.GetSysString(1337)); myswprintf(textBuffer, L"%ls\n%ls", mainGame->cbDBDecks->getItem(sel), dataManager.GetSysString(1337));
mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->textFont, textBuffer); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, textBuffer);
mainGame->PopupElement(mainGame->wQuery); mainGame->PopupElement(mainGame->wQuery);
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
prev_operation = id; prev_operation = id;
...@@ -195,7 +236,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -195,7 +236,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case BUTTON_LEAVE_GAME: { case BUTTON_LEAVE_GAME: {
if(is_modified && !mainGame->chkIgnoreDeckChanges->isChecked()) { if(is_modified && !mainGame->chkIgnoreDeckChanges->isChecked()) {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->textFont, dataManager.GetSysString(1356)); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, dataManager.GetSysString(1356));
mainGame->PopupElement(mainGame->wQuery); mainGame->PopupElement(mainGame->wQuery);
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
prev_operation = id; prev_operation = id;
...@@ -362,7 +403,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) { ...@@ -362,7 +403,7 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
case COMBOBOX_DBDECKS: { case COMBOBOX_DBDECKS: {
if(is_modified && !mainGame->chkIgnoreDeckChanges->isChecked()) { if(is_modified && !mainGame->chkIgnoreDeckChanges->isChecked()) {
mainGame->gMutex.Lock(); mainGame->gMutex.Lock();
mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->textFont, dataManager.GetSysString(1356)); mainGame->SetStaticText(mainGame->stQMessage, 310, mainGame->guiFont, dataManager.GetSysString(1356));
mainGame->PopupElement(mainGame->wQuery); mainGame->PopupElement(mainGame->wQuery);
mainGame->gMutex.Unlock(); mainGame->gMutex.Unlock();
prev_operation = id; prev_operation = id;
...@@ -679,8 +720,9 @@ void DeckBuilder::GetHoveredCard() { ...@@ -679,8 +720,9 @@ void DeckBuilder::GetHoveredCard() {
irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement(); irr::gui::IGUIElement* root = mainGame->env->getRootGUIElement();
if(root->getElementFromPoint(mouse_pos) != root) if(root->getElementFromPoint(mouse_pos) != root)
return; return;
int x = mouse_pos.X; position2di pos = mainGame->ResizeReverse(mouse_pos.X, mouse_pos.Y);
int y = mouse_pos.Y; int x = pos.X;
int y = pos.Y;
int pre_code = hovered_code; int pre_code = hovered_code;
hovered_pos = 0; hovered_pos = 0;
hovered_code = 0; hovered_code = 0;
...@@ -749,8 +791,8 @@ void DeckBuilder::GetHoveredCard() { ...@@ -749,8 +791,8 @@ void DeckBuilder::GetHoveredCard() {
} }
} }
if(is_draging) { if(is_draging) {
dragx = x; dragx = mouse_pos.X;
dragy = y; dragy = mouse_pos.Y;
} }
if(!is_draging && pre_code != hovered_code) { if(!is_draging && pre_code != hovered_code) {
if(hovered_code) if(hovered_code)
......
...@@ -10,7 +10,13 @@ DeckManager deckManager; ...@@ -10,7 +10,13 @@ DeckManager deckManager;
void DeckManager::LoadLFListSingle(const char* path) { void DeckManager::LoadLFListSingle(const char* path) {
LFList* cur = NULL; LFList* cur = NULL;
#ifdef _WIN32
wchar_t fname[1024];
BufferIO::DecodeUTF8(path, fname);
FILE* fp = _wfopen(fname, L"r");
#else
FILE* fp = fopen(path, "r"); FILE* fp = fopen(path, "r");
#endif // _WIN32
char linebuf[256]; char linebuf[256];
wchar_t strBuffer[256]; wchar_t strBuffer[256];
if(fp) { if(fp) {
...@@ -51,6 +57,13 @@ void DeckManager::LoadLFListSingle(const char* path) { ...@@ -51,6 +57,13 @@ void DeckManager::LoadLFListSingle(const char* path) {
} }
void DeckManager::LoadLFList() { void DeckManager::LoadLFList() {
LoadLFListSingle("expansions/lflist.conf"); LoadLFListSingle("expansions/lflist.conf");
FileSystem::TraversalDir("./expansions", [this](const char* name, bool isdir) {
if(isdir && strcmp(name, ".") && strcmp(name, "..")) {
char fpath[1024];
sprintf(fpath, "./expansions/%s/lflist.conf", name);
LoadLFListSingle(fpath);
}
});
LoadLFListSingle("lflist.conf"); LoadLFListSingle("lflist.conf");
LFList nolimit; LFList nolimit;
myswprintf(nolimit.listName, L"N/A"); myswprintf(nolimit.listName, L"N/A");
...@@ -58,6 +71,23 @@ void DeckManager::LoadLFList() { ...@@ -58,6 +71,23 @@ void DeckManager::LoadLFList() {
nolimit.content = new std::unordered_map<int, int>; nolimit.content = new std::unordered_map<int, int>;
_lfList.push_back(nolimit); _lfList.push_back(nolimit);
} }
bool DeckManager::RenameDeck(const wchar_t* oldname, const wchar_t* newname) {
wchar_t oldfname[256];
wchar_t newfname[256];
myswprintf(oldfname, L"./deck/%ls.ydk", oldname);
myswprintf(newfname, L"./deck/%ls.ydk", newname);
#ifdef WIN32
BOOL result = MoveFileW(oldfname, newfname);
return !!result;
#else
char oldfilefn[256];
char newfilefn[256];
BufferIO::EncodeUTF8(oldfname, oldfilefn);
BufferIO::EncodeUTF8(newfname, newfilefn);
int result = rename(oldfilefn, newfilefn);
return result == 0;
#endif
}
wchar_t* DeckManager::GetLFListName(int lfhash) { wchar_t* DeckManager::GetLFListName(int lfhash) {
for(size_t i = 0; i < _lfList.size(); ++i) { for(size_t i = 0; i < _lfList.size(); ++i) {
if(_lfList[i].hash == (unsigned int)lfhash) { if(_lfList[i].hash == (unsigned int)lfhash) {
...@@ -266,4 +296,13 @@ bool DeckManager::DeleteDeck(Deck& deck, const wchar_t* name) { ...@@ -266,4 +296,13 @@ bool DeckManager::DeleteDeck(Deck& deck, const wchar_t* name) {
return result == 0; return result == 0;
#endif #endif
} }
int DeckManager::TypeCount(std::vector<code_pointer> list, unsigned int ctype) {
int res = 0;
for(size_t i = 0; i < list.size(); ++i) {
code_pointer cur = list[i];
if(cur->second.type & ctype)
res++;
}
return res;
}
} }
...@@ -45,6 +45,9 @@ public: ...@@ -45,6 +45,9 @@ public:
bool LoadDeck(const wchar_t* file); bool LoadDeck(const wchar_t* file);
bool SaveDeck(Deck& deck, const wchar_t* name); bool SaveDeck(Deck& deck, const wchar_t* name);
bool DeleteDeck(Deck& deck, const wchar_t* name); bool DeleteDeck(Deck& deck, const wchar_t* name);
static bool RenameDeck(const wchar_t* oldname, const wchar_t* newname);
wchar_t DeckFormatBuffer[128];
int TypeCount(std::vector<code_pointer> list, unsigned int ctype);
}; };
extern DeckManager deckManager; extern DeckManager deckManager;
......
This diff is collapsed.
This diff is collapsed.
...@@ -33,6 +33,11 @@ private: ...@@ -33,6 +33,11 @@ private:
static wchar_t event_string[256]; static wchar_t event_string[256];
static mtrandom rnd; static mtrandom rnd;
public: public:
static unsigned int temp_ip;
static unsigned short temp_port;
static unsigned short temp_ver;
static bool try_needed;
static bool StartClient(unsigned int ip, unsigned short port, bool create_game = true); static bool StartClient(unsigned int ip, unsigned short port, bool create_game = true);
static void ConnectTimeout(evutil_socket_t fd, short events, void* arg); static void ConnectTimeout(evutil_socket_t fd, short events, void* arg);
static void StopClient(bool is_exiting = false); static void StopClient(bool is_exiting = false);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -9,22 +9,33 @@ namespace ygo { ...@@ -9,22 +9,33 @@ namespace ygo {
class ImageManager { class ImageManager {
public: public:
std::vector<std::wstring> ImageList[7];
int saved_image_id[7];
bool Initial(); bool Initial();
//random image
irr::video::ITexture* GetRandomImage(int image_type);
irr::video::ITexture* GetRandomImage(int image_type, s32 width, s32 height);
void RefreshRandomImageList();
void RefreshImageDir(std::wstring path, int image_type);
void SetDevice(irr::IrrlichtDevice* dev); void SetDevice(irr::IrrlichtDevice* dev);
void ClearTexture(); void ClearTexture();
void RemoveTexture(int code); void RemoveTexture(int code);
void ResizeTexture();
irr::video::ITexture* GetTextureFromFile(char* file, s32 width, s32 height); irr::video::ITexture* GetTextureFromFile(char* file, s32 width, s32 height);
irr::video::ITexture* GetTexture(int code); irr::video::ITexture* GetTextureUnknown(s32 width, s32 height, int index);
irr::video::ITexture* GetTextureExpansions(char* file, s32 width, s32 height);
irr::video::ITexture* GetTextureExpansionsDirectry(const char* path, char* file, s32 width, s32 height);
irr::video::ITexture* GetTexture(int code, bool fit = false);
irr::video::ITexture* GetTextureThumb(int code); irr::video::ITexture* GetTextureThumb(int code);
irr::video::ITexture* GetTextureField(int code); irr::video::ITexture* GetTextureField(int code);
std::unordered_map<int, irr::video::ITexture*> tMap; std::unordered_map<int, irr::video::ITexture*> tMap[2];
std::unordered_map<int, irr::video::ITexture*> tThumb; std::unordered_map<int, irr::video::ITexture*> tThumb;
std::unordered_map<int, irr::video::ITexture*> tFields; std::unordered_map<int, irr::video::ITexture*> tFields;
irr::IrrlichtDevice* device; irr::IrrlichtDevice* device;
irr::video::IVideoDriver* driver; irr::video::IVideoDriver* driver;
irr::video::ITexture* tCover[2]; irr::video::ITexture* tCover[4];
irr::video::ITexture* tUnknown; irr::video::ITexture* tUnknown[3];
irr::video::ITexture* tAct; irr::video::ITexture* tAct;
irr::video::ITexture* tAttack; irr::video::ITexture* tAttack;
irr::video::ITexture* tNegated; irr::video::ITexture* tNegated;
...@@ -42,8 +53,12 @@ public: ...@@ -42,8 +53,12 @@ public:
irr::video::ITexture* tBackGround; irr::video::ITexture* tBackGround;
irr::video::ITexture* tBackGround_menu; irr::video::ITexture* tBackGround_menu;
irr::video::ITexture* tBackGround_deck; irr::video::ITexture* tBackGround_deck;
irr::video::ITexture* tCardType;
irr::video::ITexture* tField[2]; irr::video::ITexture* tField[2];
irr::video::ITexture* tFieldTransparent[2]; irr::video::ITexture* tFieldTransparent[2];
irr::video::ITexture* tRScale[14];
irr::video::ITexture* tLScale[14];
irr::video::ITexture* tClock;
}; };
extern ImageManager imageManager; extern ImageManager imageManager;
......
...@@ -21,6 +21,7 @@ Materials::Materials() { ...@@ -21,6 +21,7 @@ Materials::Materials() {
SetS3DVertex(vChainNum, -0.35f, -0.35f, 0.35f, 0.35f, 0, 1, 0, 0, 0.19375f, 0.2421875f); SetS3DVertex(vChainNum, -0.35f, -0.35f, 0.35f, 0.35f, 0, 1, 0, 0, 0.19375f, 0.2421875f);
SetS3DVertex(vActivate, -0.5f, -0.5f, 0.5f, 0.5f, 0, 1, 0, 0, 1, 1); SetS3DVertex(vActivate, -0.5f, -0.5f, 0.5f, 0.5f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vField, -1.0f, -4.0f, 9.0f, 4.0f, 0, 1, 0, 0, 1, 1); SetS3DVertex(vField, -1.0f, -4.0f, 9.0f, 4.0f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vPScale, -0.35f, -0.5, 0.35, 0.5f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vFieldSpell, 1.2f, -3.2f, 6.7f, 3.2f, 0, 1, 0, 0, 1, 1); SetS3DVertex(vFieldSpell, 1.2f, -3.2f, 6.7f, 3.2f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vFieldSpell1, 1.2f, 0.8f, 6.7f, 3.2f, 0, 1, 0, 0.2f, 1, 0.63636f); SetS3DVertex(vFieldSpell1, 1.2f, 0.8f, 6.7f, 3.2f, 0, 1, 0, 0.2f, 1, 0.63636f);
SetS3DVertex(vFieldSpell2, 1.2f, -3.2f, 6.7f, -0.8f, 0, 1, 1, 0.63636f, 0, 0.2f); SetS3DVertex(vFieldSpell2, 1.2f, -3.2f, 6.7f, -0.8f, 0, 1, 1, 0.63636f, 0, 0.2f);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
project "ikpmp3"
kind "StaticLib"
files { "*.cpp", "*.h", "decoder/*.c", "decoder/*.h" }
includedirs { "../irrklang/include" }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment