Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro-2pick
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
ygopro-2pick
Commits
1147fb51
Commit
1147fb51
authored
Apr 17, 2018
by
nanahira
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
625e0d1e
d8a1c420
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1894 additions
and
0 deletions
+1894
-0
.gitignore
.gitignore
+1
-0
gframe/CGUISkinSystem/CConfigMap.cpp
gframe/CGUISkinSystem/CConfigMap.cpp
+79
-0
gframe/CGUISkinSystem/CConfigMap.h
gframe/CGUISkinSystem/CConfigMap.h
+31
-0
gframe/CGUISkinSystem/CGUIProgressBar.cpp
gframe/CGUISkinSystem/CGUIProgressBar.cpp
+88
-0
gframe/CGUISkinSystem/CGUIProgressBar.h
gframe/CGUISkinSystem/CGUIProgressBar.h
+49
-0
gframe/CGUISkinSystem/CGUISkinSystem.cpp
gframe/CGUISkinSystem/CGUISkinSystem.cpp
+288
-0
gframe/CGUISkinSystem/CGUISkinSystem.h
gframe/CGUISkinSystem/CGUISkinSystem.h
+53
-0
gframe/CGUISkinSystem/CImageGUISkin.cpp
gframe/CGUISkinSystem/CImageGUISkin.cpp
+491
-0
gframe/CGUISkinSystem/CImageGUISkin.h
gframe/CGUISkinSystem/CImageGUISkin.h
+152
-0
gframe/CGUISkinSystem/clipRects.h
gframe/CGUISkinSystem/clipRects.h
+68
-0
gframe/CXMLRegistry/CXMLNode.cpp
gframe/CXMLRegistry/CXMLNode.cpp
+175
-0
gframe/CXMLRegistry/CXMLNode.h
gframe/CXMLRegistry/CXMLNode.h
+56
-0
gframe/CXMLRegistry/CXMLRegistry.cpp
gframe/CXMLRegistry/CXMLRegistry.cpp
+275
-0
gframe/CXMLRegistry/CXMLRegistry.h
gframe/CXMLRegistry/CXMLRegistry.h
+65
-0
gframe/game.cpp
gframe/game.cpp
+18
-0
gframe/game.h
gframe/game.h
+4
-0
system.conf
system.conf
+1
-0
No files found.
.gitignore
View file @
1147fb51
...
...
@@ -53,6 +53,7 @@
/fonts
/replay
/single
/skin
/sound/*.wav
/sound/custom
/sound/BGM
...
...
gframe/CGUISkinSystem/CConfigMap.cpp
0 → 100644
View file @
1147fb51
#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.0
f
;
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
);
}
gframe/CGUISkinSystem/CConfigMap.h
0 → 100644
View file @
1147fb51
#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
gframe/CGUISkinSystem/CGUIProgressBar.cpp
0 → 100644
View file @
1147fb51
#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.0
f
;
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
);
}
}
}
gframe/CGUISkinSystem/CGUIProgressBar.h
0 → 100644
View file @
1147fb51
#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
gframe/CGUISkinSystem/CGUISkinSystem.cpp
0 → 100644
View file @
1147fb51
#include "CGUISkinSystem.h"
CGUISkinSystem
::
CGUISkinSystem
(
core
::
string
<
wchar_t
>
path
,
IrrlichtDevice
*
dev
)
{
device
=
dev
;
skinsPath
=
path
;
fs
=
dev
->
getFileSystem
();
this
->
loadSkinList
();
}
core
::
array
<
core
::
stringw
>
CGUISkinSystem
::
listSkins
()
{
return
skinsList
;
}
// This is our version of the skinloader
// Generate a list of all directory names in skinsPath that have a skin.xml in them
// Don't rely on working directory going in.
// Careful with changeworkingdirectoryto and relative paths,
// remember that they are relative to the CURRENT working directory
bool
CGUISkinSystem
::
loadSkinList
()
{
io
::
IFileList
*
fileList
;
int
i
;
io
::
path
oldpath
=
fs
->
getWorkingDirectory
();
fs
->
changeWorkingDirectoryTo
(
skinsPath
);
fileList
=
fs
->
createFileList
();
i
=
fileList
->
getFileCount
();
core
::
stringw
tmp
;
while
(
i
--
)
{
// Check only directories, skip . and ..
// Side effect, on linux this ignores hidden directories
if
(
fileList
->
isDirectory
(
i
)
&&
!
fileList
->
getFileName
(
i
).
equalsn
(
"."
,
1
))
{
if
(
fs
->
existFile
(
fileList
->
getFileName
(
i
)
+
SKINSYSTEM_SKINFILE
))
{
tmp
=
fileList
->
getFileName
(
i
);
skinsList
.
push_back
(
tmp
);
}
}
}
fileList
->
drop
();
fs
->
changeWorkingDirectoryTo
(
oldpath
);
if
(
skinsList
.
size
()
>
0
)
return
true
;
else
return
false
;
}
gui
::
CGUIProgressBar
*
CGUISkinSystem
::
addProgressBar
(
gui
::
IGUIElement
*
parent
,
core
::
rect
<
s32
>
rect
,
bool
bindColorsToSkin
)
{
gui
::
CGUIProgressBar
*
bar
=
new
gui
::
CGUIProgressBar
(
parent
,
device
->
getGUIEnvironment
(),
rect
,
bindColorsToSkin
);
//gui::CImageGUISkin* skin = (gui::CImageGUISkin*)device->getGUIEnvironment()->getSkin();
parent
->
addChild
(
bar
);
bar
->
drop
();
return
bar
;
}
bool
CGUISkinSystem
::
populateTreeView
(
gui
::
IGUITreeView
*
control
,
const
core
::
stringc
&
skinname
)
{
bool
ret
=
false
;
io
::
path
oldpath
=
fs
->
getWorkingDirectory
();
fs
->
changeWorkingDirectoryTo
(
skinsPath
);
registry
=
new
CXMLRegistry
(
fs
);
if
(
!
registry
->
loadFile
(
SKINSYSTEM_SKINFILE
,
skinname
.
c_str
()))
{
return
ret
;
}
ret
=
registry
->
populateTreeView
(
control
);
delete
registry
;
registry
=
NULL
;
fs
->
changeWorkingDirectoryTo
(
oldpath
);
return
ret
;
}
void
CGUISkinSystem
::
ParseGUIElementStyle
(
gui
::
SImageGUIElementStyle
&
elem
,
const
core
::
stringc
&
name
,
bool
nullcolors
)
{
core
::
stringw
context
;
core
::
stringc
ctmp
,
err
=
""
;
context
=
L"Skin/"
;
context
+=
name
;
core
::
rect
<
u32
>
box
;
video
::
SColor
col
;
ctmp
=
registry
->
getValueAsCStr
(
L"texture"
,
context
.
c_str
());
if
(
!
ctmp
.
size
())
err
+=
"Could not load texture property from skin file"
;
elem
.
Texture
=
device
->
getVideoDriver
()
->
getTexture
(
ctmp
);
box
=
registry
->
getValueAsRect
((
context
+
"/SrcBorder"
).
c_str
());
elem
.
SrcBorder
.
Top
=
box
.
UpperLeftCorner
.
X
;
elem
.
SrcBorder
.
Left
=
box
.
UpperLeftCorner
.
Y
;
elem
.
SrcBorder
.
Bottom
=
box
.
LowerRightCorner
.
X
;
elem
.
SrcBorder
.
Right
=
box
.
LowerRightCorner
.
Y
;
box
=
registry
->
getValueAsRect
((
context
+
"/DstBorder"
).
c_str
());
elem
.
DstBorder
.
Top
=
box
.
UpperLeftCorner
.
X
;
elem
.
DstBorder
.
Left
=
box
.
UpperLeftCorner
.
Y
;
elem
.
DstBorder
.
Bottom
=
box
.
LowerRightCorner
.
X
;
elem
.
DstBorder
.
Right
=
box
.
LowerRightCorner
.
Y
;
if
(
nullcolors
)
elem
.
Color
=
NULL
;
col
=
registry
->
getValueAsColor
((
context
+
"/Color"
).
c_str
());
if
(
col
!=
NULL
)
elem
.
Color
=
col
;
else
{
col
=
registry
->
getValueAsColor
((
context
+
"/Colour"
).
c_str
());
if
(
col
!=
NULL
)
elem
.
Color
=
col
;
}
}
// Because my 'xmlloader/registry', already has the data access components
// We skip the 'configreader and skinloader' steps and just load right from the registry into the skin config
// Then create the skin from that, and set it up
// TO maintain compatability in case of upgrades
// We dont touch the iterface to the skin itself.
gui
::
CImageGUISkin
*
CGUISkinSystem
::
loadSkinFromFile
(
const
c8
*
skinname
)
{
gui
::
CImageGUISkin
*
skin
;
gui
::
SImageGUISkinConfig
skinConfig
;
gui
::
EGUI_SKIN_TYPE
fallbackType
;
gui
::
IGUISkin
*
fallbackSkin
;
s32
i
,
x
;
core
::
stringc
tmp
;
core
::
stringw
wtmp
;
core
::
stringc
path
=
"./"
;
path
+=
skinname
;
if
(
!
registry
->
loadFile
(
SKINSYSTEM_SKINFILE
,
path
.
c_str
()))
{
return
NULL
;
}
// Easiest way to see if an xml is loading correctly
// is to make the registry write out the root node and see what comes out.
//registry->writeFile("Skin",".");
// To switch on the fly, we have to set the skin to the fallback skin first
tmp
=
registry
->
getValueAsCStr
(
L"skin"
,
L"Skin/Properties/Fallback"
);
// Always default to metalic
fallbackType
=
gui
::
EGST_WINDOWS_METALLIC
;
if
(
tmp
.
equals_ignore_case
(
"EGST_WINDOWS_CLASSIC"
))
fallbackType
=
gui
::
EGST_WINDOWS_CLASSIC
;
else
if
(
tmp
.
equals_ignore_case
(
"EGST_BURNING_SKIN"
))
fallbackType
=
gui
::
EGST_BURNING_SKIN
;
// I'm not dealing with the 'unknown skin'
fallbackSkin
=
device
->
getGUIEnvironment
()
->
createSkin
(
fallbackType
);
device
->
getGUIEnvironment
()
->
setSkin
(
fallbackSkin
);
fallbackSkin
->
drop
();
skin
=
new
gui
::
CImageGUISkin
(
device
->
getVideoDriver
(),
device
->
getGUIEnvironment
()
->
getSkin
());
fs
->
changeWorkingDirectoryTo
(
path
.
c_str
());
ParseGUIElementStyle
(
skinConfig
.
Button
,
"Button"
);
ParseGUIElementStyle
(
skinConfig
.
ButtonPressed
,
"Button/Pressed"
);
ParseGUIElementStyle
(
skinConfig
.
ButtonDisabled
,
"Button/ButtonDisabled"
);
ParseGUIElementStyle
(
skinConfig
.
SunkenPane
,
"SunkenPane"
);
ParseGUIElementStyle
(
skinConfig
.
Window
,
"Window"
);
ParseGUIElementStyle
(
skinConfig
.
ProgressBar
,
"ProgressBar"
,
true
);
ParseGUIElementStyle
(
skinConfig
.
ProgressBarFilled
,
"ProgressBar/Filled"
,
true
);
ParseGUIElementStyle
(
skinConfig
.
TabBody
,
"TabControl"
);
ParseGUIElementStyle
(
skinConfig
.
TabButton
,
"TabControl/TabButton"
);
ParseGUIElementStyle
(
skinConfig
.
TabButtonPressed
,
"TabControl/TabButtonPressed"
);
ParseGUIElementStyle
(
skinConfig
.
MenuBar
,
"MenuBar"
);
ParseGUIElementStyle
(
skinConfig
.
MenuPane
,
"MenuBar/MenuPane"
);
ParseGUIElementStyle
(
skinConfig
.
MenuPressed
,
"MenuBar/MenuPressed"
);
ParseGUIElementStyle
(
skinConfig
.
CheckBox
,
"CheckBox"
);
ParseGUIElementStyle
(
skinConfig
.
CheckBoxDisabled
,
"CheckBox/CheckBoxDisabled"
);
ParseGUIElementStyle
(
skinConfig
.
ComboBox
,
"ComboBox"
);
ParseGUIElementStyle
(
skinConfig
.
ComboBoxDisabled
,
"ComboBox/ComboBoxDisabled"
);
skinConfig
.
CheckBoxColor
=
registry
->
getValueAsColor
(
L"Skin/Global/CheckBoxColor"
);
// If there was no progress bar colors set, set them in the config to the defaults
// otherwise their 0,0,0,0. This is neccicary for the old klagui.
if
(
skinConfig
.
ProgressBar
.
Color
==
NULL
)
skinConfig
.
ProgressBar
.
Color
=
video
::
SColor
();
if
(
skinConfig
.
ProgressBarFilled
.
Color
==
NULL
)
skinConfig
.
ProgressBarFilled
.
Color
=
video
::
SColor
(
255
,
255
,
0
,
0
);
// Load in the Info
loadProperty
((
core
::
stringw
)
L"Name"
,
skin
);
loadProperty
((
core
::
stringw
)
L"Author"
,
skin
);
loadProperty
((
core
::
stringw
)
L"Version"
,
skin
);
loadProperty
((
core
::
stringw
)
L"Date"
,
skin
);
loadProperty
((
core
::
stringw
)
L"Desc"
,
skin
);
skin
->
loadConfig
(
skinConfig
);
tmp
=
registry
->
getValueAsCStr
(
L"texture"
,
L"Skin/Properties/Font"
);
gui
::
IGUIFont
*
font
=
device
->
getGUIEnvironment
()
->
getFont
(
tmp
.
c_str
());
if
(
font
!=
0
)
{
device
->
getGUIEnvironment
()
->
getSkin
()
->
setFont
(
font
,
gui
::
EGDF_DEFAULT
);
device
->
getGUIEnvironment
()
->
getSkin
()
->
setFont
(
font
,
gui
::
EGDF_WINDOW
);
}
// Get and set global alpha, problem with this, you can't set it to 0
// He does this to make ALL the default stuff completly transparent
// This has the downside that it whipes out things like checkbox and window button colors
video
::
SColor
newCol
=
video
::
SColor
();
video
::
SColor
oldCol
=
newCol
;
x
=
registry
->
getValueAsInt
(
L"guialpha"
,
L"Skin/Global/"
);
if
(
x
&&
x
!=
NULL
)
{
i
=
gui
::
EGDC_COUNT
;
while
(
i
--
)
{
oldCol
=
skin
->
getColor
((
gui
::
EGUI_DEFAULT_COLOR
)
i
);
newCol
=
oldCol
;
newCol
.
setAlpha
(
x
);
skin
->
setColor
((
gui
::
EGUI_DEFAULT_COLOR
)
i
,
newCol
);
}
}
checkSkinColor
(
gui
::
EGDC_3D_DARK_SHADOW
,
L"Skin/Global/EGDC_32_DARK_SHADOW"
,
skin
);
checkSkinColor
(
gui
::
EGDC_3D_SHADOW
,
L"Skin/Global/EGDC_3D_SHADOW"
,
skin
);
checkSkinColor
(
gui
::
EGDC_3D_FACE
,
L"Skin/Global/EGDC_3D_FACE"
,
skin
);
checkSkinColor
(
gui
::
EGDC_3D_HIGH_LIGHT
,
L"Skin/Global/EGDC_3D_HIGH_LIGHT"
,
skin
);
checkSkinColor
(
gui
::
EGDC_3D_LIGHT
,
L"Skin/Global/EGDC_3D_LIGHT"
,
skin
);
checkSkinColor
(
gui
::
EGDC_ACTIVE_BORDER
,
L"Skin/Global/EGDC_ACTIVE_BORDER"
,
skin
);
checkSkinColor
(
gui
::
EGDC_ACTIVE_CAPTION
,
L"Skin/Global/EGDC_ACTIVE_CAPTION"
,
skin
);
checkSkinColor
(
gui
::
EGDC_APP_WORKSPACE
,
L"Skin/Global/EGDC_APP_WORKSPACE"
,
skin
);
checkSkinColor
(
gui
::
EGDC_BUTTON_TEXT
,
L"Skin/Global/EGDC_BUTTON_TEXT"
,
skin
);
checkSkinColor
(
gui
::
EGDC_GRAY_TEXT
,
L"Skin/Global/EGDC_GRAY_TEXT"
,
skin
);
checkSkinColor
(
gui
::
EGDC_HIGH_LIGHT_TEXT
,
L"Skin/Global/EGDC_HIGH_LIGHT_TEXT"
,
skin
);
checkSkinColor
(
gui
::
EGDC_INACTIVE_BORDER
,
L"Skin/Global/EGDC_INACTIVE_BORDER"
,
skin
);
checkSkinColor
(
gui
::
EGDC_INACTIVE_CAPTION
,
L"Skin/Global/EGDC_INACTIVE_CAPTION"
,
skin
);
checkSkinColor
(
gui
::
EGDC_TOOLTIP
,
L"Skin/Global/EGDC_TOOLTIP"
,
skin
);
checkSkinColor
(
gui
::
EGDC_TOOLTIP_BACKGROUND
,
L"Skin/Global/EGDC_TOOLTIP_BACKGROUND"
,
skin
);
checkSkinColor
(
gui
::
EGDC_SCROLLBAR
,
L"Skin/Global/EGDC_SCROLLBAR"
,
skin
);
checkSkinColor
(
gui
::
EGDC_WINDOW
,
L"Skin/Global/EGDC_WINDOW"
,
skin
);
checkSkinColor
(
gui
::
EGDC_WINDOW_SYMBOL
,
L"Skin/Global/EGDC_WINDOW_SYMBOL"
,
skin
);
checkSkinColor
(
gui
::
EGDC_ICON
,
L"Skin/Global/EGDC_ICON"
,
skin
);
checkSkinColor
(
gui
::
EGDC_ICON_HIGH_LIGHT
,
L"Skin/Global/EGDC_ICON_HIGH_LIGHT"
,
skin
);
checkSkinSize
(
gui
::
EGDS_WINDOW_BUTTON_WIDTH
,
L"Skin/Global/WindowButton"
,
L"width"
,
skin
);
checkSkinSize
(
gui
::
EGDS_TITLEBARTEXT_DISTANCE_X
,
L"Skin/Global/Caption"
,
L"tbardistancex"
,
skin
);
checkSkinSize
(
gui
::
EGDS_TITLEBARTEXT_DISTANCE_Y
,
L"Skin/Global/Caption"
,
L"tbardistancey"
,
skin
);
return
skin
;
}
core
::
stringw
CGUISkinSystem
::
getProperty
(
core
::
stringw
key
)
{
gui
::
CImageGUISkin
*
skin
=
(
gui
::
CImageGUISkin
*
)
device
->
getGUIEnvironment
()
->
getSkin
();
return
skin
->
getProperty
(
key
);
}
bool
CGUISkinSystem
::
checkSkinColor
(
gui
::
EGUI_DEFAULT_COLOR
colToSet
,
const
wchar_t
*
context
,
gui
::
CImageGUISkin
*
skin
)
{
video
::
SColor
col
=
registry
->
getValueAsColor
(
context
);
if
(
col
!=
NULL
)
{
skin
->
setColor
(
colToSet
,
col
);
return
true
;
}
return
false
;
}
bool
CGUISkinSystem
::
checkSkinSize
(
gui
::
EGUI_DEFAULT_SIZE
sizeToSet
,
const
wchar_t
*
context
,
const
wchar_t
*
key
,
gui
::
CImageGUISkin
*
skin
)
{
u16
i
=
registry
->
getValueAsInt
(
key
,
context
);
if
(
i
!=
NULL
)
{
skin
->
setSize
(
sizeToSet
,
i
);
return
true
;
}
return
false
;
}
bool
CGUISkinSystem
::
loadProperty
(
core
::
stringw
key
,
gui
::
CImageGUISkin
*
skin
)
{
core
::
stringw
wtmp
=
"Skin/Properties/"
;
wtmp
+=
key
;
wtmp
=
registry
->
getValueAsCStr
(
L"data"
,
wtmp
.
c_str
());
if
(
wtmp
.
size
())
{
skin
->
setProperty
(
key
,
wtmp
);
return
true
;
}
return
false
;
}
bool
CGUISkinSystem
::
applySkin
(
const
wchar_t
*
skinname
)
{
io
::
path
oldpath
=
fs
->
getWorkingDirectory
();
core
::
stringc
tmp
=
skinname
;
fs
->
changeWorkingDirectoryTo
(
skinsPath
);
registry
=
new
CXMLRegistry
(
fs
);
gui
::
CImageGUISkin
*
skin
=
loadSkinFromFile
(
tmp
.
c_str
());
if
(
skin
==
NULL
)
return
false
;
device
->
getGUIEnvironment
()
->
setSkin
(
skin
);
// If we're going to switch skin we need to find all the progress bars and overwrite their colors
skin
->
drop
();
delete
registry
;
registry
=
NULL
;
fs
->
changeWorkingDirectoryTo
(
oldpath
);
return
true
;
}
CGUISkinSystem
::~
CGUISkinSystem
()
{
skinsList
.
clear
();
}
\ No newline at end of file
gframe/CGUISkinSystem/CGUISkinSystem.h
0 → 100644
View file @
1147fb51
#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
gframe/CGUISkinSystem/CImageGUISkin.cpp
0 → 100644
View file @
1147fb51
#include "CImageGUISkin.h"
#include <IVideoDriver.h>
#include <ITexture.h>
#include <IGUIElement.h>
#include "clipRects.h"
namespace
irr
{
namespace
gui
{
CImageGUISkin
::
CImageGUISkin
(
video
::
IVideoDriver
*
driver
,
IGUISkin
*
fallbackSkin
)
{
VideoDriver
=
driver
;
FallbackSkin
=
fallbackSkin
;
FallbackSkin
->
grab
();
}
CImageGUISkin
::~
CImageGUISkin
()
{
FallbackSkin
->
drop
();
properties
.
clear
();
}
void
CImageGUISkin
::
setProperty
(
core
::
stringw
key
,
core
::
stringw
value
)
{
properties
.
set
(
key
,
value
);
}
core
::
stringw
CImageGUISkin
::
getProperty
(
core
::
stringw
key
)
{
core
::
map
<
core
::
stringw
,
core
::
stringw
>::
Node
*
node
=
properties
.
find
(
key
);
if
(
node
==
0
)
return
core
::
stringw
(
""
);
else
return
node
->
getValue
();
}
void
CImageGUISkin
::
loadConfig
(
const
SImageGUISkinConfig
&
config
)
{
Config
=
config
;
}
video
::
SColor
CImageGUISkin
::
getColor
(
EGUI_DEFAULT_COLOR
color
)
const
{
return
FallbackSkin
->
getColor
(
color
);
}
void
CImageGUISkin
::
setColor
(
EGUI_DEFAULT_COLOR
which
,
video
::
SColor
newColor
)
{
FallbackSkin
->
setColor
(
which
,
newColor
);
}
s32
CImageGUISkin
::
getSize
(
EGUI_DEFAULT_SIZE
size
)
const
{
return
FallbackSkin
->
getSize
(
size
);
}
const
wchar_t
*
CImageGUISkin
::
getDefaultText
(
EGUI_DEFAULT_TEXT
text
)
const
{
return
FallbackSkin
->
getDefaultText
(
text
);
}
void
CImageGUISkin
::
setDefaultText
(
EGUI_DEFAULT_TEXT
which
,
const
wchar_t
*
newText
)
{
FallbackSkin
->
setDefaultText
(
which
,
newText
);
}
void
CImageGUISkin
::
setSize
(
EGUI_DEFAULT_SIZE
which
,
s32
size
)
{
FallbackSkin
->
setSize
(
which
,
size
);
}
IGUIFont
*
CImageGUISkin
::
getFont
(
EGUI_DEFAULT_FONT
defaultFont
)
const
{
return
FallbackSkin
->
getFont
(
defaultFont
);
}
void
CImageGUISkin
::
setFont
(
IGUIFont
*
font
,
EGUI_DEFAULT_FONT
defaultFont
)
{
FallbackSkin
->
setFont
(
font
,
defaultFont
);
}
IGUISpriteBank
*
CImageGUISkin
::
getSpriteBank
()
const
{
return
FallbackSkin
->
getSpriteBank
();
}
void
CImageGUISkin
::
setSpriteBank
(
IGUISpriteBank
*
bank
)
{
FallbackSkin
->
setSpriteBank
(
bank
);
}
u32
CImageGUISkin
::
getIcon
(
EGUI_DEFAULT_ICON
icon
)
const
{
return
FallbackSkin
->
getIcon
(
icon
);
}
void
CImageGUISkin
::
setIcon
(
EGUI_DEFAULT_ICON
icon
,
u32
index
)
{
FallbackSkin
->
setIcon
(
icon
,
index
);
}
void
CImageGUISkin
::
draw3DButtonPaneStandard
(
IGUIElement
*
element
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
)
{
if
(
element
->
isEnabled
())
{
if
(
!
Config
.
Button
.
Texture
)
{
FallbackSkin
->
draw3DButtonPaneStandard
(
element
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
Button
,
rect
,
clip
);
}
else
{
if
(
!
Config
.
ButtonDisabled
.
Texture
)
{
FallbackSkin
->
draw3DButtonPaneStandard
(
element
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
ButtonDisabled
,
rect
,
clip
);
}
}
void
CImageGUISkin
::
draw3DButtonPanePressed
(
IGUIElement
*
element
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
)
{
if
(
!
Config
.
Button
.
Texture
)
{
FallbackSkin
->
draw3DButtonPanePressed
(
element
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
ButtonPressed
,
rect
,
clip
);
}
void
CImageGUISkin
::
draw3DSunkenPane
(
IGUIElement
*
element
,
video
::
SColor
bgcolor
,
bool
flat
,
bool
fillBackGround
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
)
{
if
(
element
->
getType
()
==
EGUIET_MENU
)
{
if
(
!
Config
.
MenuPressed
.
Texture
)
{
FallbackSkin
->
draw3DSunkenPane
(
element
,
bgcolor
,
flat
,
fillBackGround
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
MenuPressed
,
rect
,
clip
);
}
else
if
(
element
->
getType
()
==
EGUIET_CHECK_BOX
)
{
if
(
element
->
isEnabled
())
{
if
(
!
Config
.
CheckBox
.
Texture
)
{
FallbackSkin
->
draw3DSunkenPane
(
element
,
bgcolor
,
flat
,
fillBackGround
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
CheckBox
,
rect
,
clip
);
}
else
{
if
(
!
Config
.
CheckBoxDisabled
.
Texture
)
{
FallbackSkin
->
draw3DSunkenPane
(
element
,
bgcolor
,
flat
,
fillBackGround
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
CheckBoxDisabled
,
rect
,
clip
);
}
}
else
if
(
element
->
getType
()
==
EGUIET_COMBO_BOX
)
{
if
(
element
->
isEnabled
())
{
if
(
!
Config
.
ComboBox
.
Texture
)
{
FallbackSkin
->
draw3DSunkenPane
(
element
,
bgcolor
,
flat
,
fillBackGround
,
rect
,
clip
);
return
;
}
if
(
fillBackGround
)
FallbackSkin
->
draw2DRectangle
(
element
,
bgcolor
,
rect
,
clip
);
drawElementStyle
(
Config
.
ComboBox
,
rect
,
clip
);
}
else
{
if
(
!
Config
.
ComboBoxDisabled
.
Texture
)
{
FallbackSkin
->
draw3DSunkenPane
(
element
,
bgcolor
,
flat
,
fillBackGround
,
rect
,
clip
);
return
;
}
if
(
fillBackGround
)
FallbackSkin
->
draw2DRectangle
(
element
,
bgcolor
,
rect
,
clip
);
drawElementStyle
(
Config
.
ComboBoxDisabled
,
rect
,
clip
);
}
}
else
{
if
(
!
Config
.
SunkenPane
.
Texture
)
{
FallbackSkin
->
draw3DSunkenPane
(
element
,
bgcolor
,
flat
,
fillBackGround
,
rect
,
clip
);
return
;
}
if
(
fillBackGround
)
FallbackSkin
->
draw2DRectangle
(
element
,
bgcolor
,
rect
,
clip
);
drawElementStyle
(
Config
.
SunkenPane
,
rect
,
clip
);
}
}
// 1.7 updates by Mamnarock
core
::
rect
<
s32
>
CImageGUISkin
::
draw3DWindowBackground
(
IGUIElement
*
element
,
bool
drawTitleBar
,
video
::
SColor
titleBarColor
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
,
core
::
rect
<
s32
>*
checkClientArea
)
{
if
(
!
Config
.
Window
.
Texture
)
{
return
FallbackSkin
->
draw3DWindowBackground
(
element
,
drawTitleBar
,
titleBarColor
,
rect
,
clip
);
}
drawElementStyle
(
Config
.
Window
,
rect
,
clip
);
return
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
+
Config
.
Window
.
DstBorder
.
Left
,
rect
.
UpperLeftCorner
.
Y
,
rect
.
LowerRightCorner
.
X
-
Config
.
Window
.
DstBorder
.
Right
,
rect
.
UpperLeftCorner
.
Y
+
Config
.
Window
.
DstBorder
.
Top
);
}
void
CImageGUISkin
::
draw3DMenuPane
(
IGUIElement
*
element
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
)
{
if
(
!
Config
.
MenuPane
.
Texture
)
{
FallbackSkin
->
draw3DToolBar
(
element
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
MenuPane
,
rect
,
clip
);
}
void
CImageGUISkin
::
draw3DToolBar
(
IGUIElement
*
element
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
)
{
if
(
!
Config
.
MenuBar
.
Texture
)
{
FallbackSkin
->
draw3DToolBar
(
element
,
rect
,
clip
);
return
;
}
drawElementStyle
(
Config
.
MenuBar
,
rect
,
clip
);
}
void
CImageGUISkin
::
draw3DTabButton
(
IGUIElement
*
element
,
bool
active
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
,
gui
::
EGUI_ALIGNMENT
alignment
)
{
if
(
active
)
{
if
(
!
Config
.
TabButtonPressed
.
Texture
)
{
FallbackSkin
->
draw3DTabButton
(
element
,
active
,
rect
,
clip
,
alignment
);
return
;
}
drawElementStyle
(
Config
.
TabButtonPressed
,
rect
,
clip
);
}
else
{
if
(
!
Config
.
TabButton
.
Texture
)
{
FallbackSkin
->
draw3DTabButton
(
element
,
active
,
rect
,
clip
,
alignment
);
return
;
}
drawElementStyle
(
Config
.
TabButton
,
rect
,
clip
);
}
}
void
CImageGUISkin
::
draw3DTabBody
(
IGUIElement
*
element
,
bool
border
,
bool
background
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
,
s32
tabHeight
,
gui
::
EGUI_ALIGNMENT
alignment
)
{
core
::
rect
<
s32
>
newclip
,
newrect
;
if
(
!
Config
.
TabBody
.
Texture
)
{
FallbackSkin
->
draw3DTabBody
(
element
,
border
,
background
,
rect
,
clip
,
tabHeight
,
alignment
);
return
;
}
newclip
.
LowerRightCorner
.
set
(
clip
->
LowerRightCorner
);
newclip
.
UpperLeftCorner
.
set
(
clip
->
UpperLeftCorner
.
X
,
clip
->
UpperLeftCorner
.
Y
+
tabHeight
);
newrect
.
LowerRightCorner
.
set
(
rect
.
LowerRightCorner
);
newrect
.
UpperLeftCorner
.
set
(
rect
.
UpperLeftCorner
.
X
,
rect
.
LowerRightCorner
.
Y
+
tabHeight
);
drawElementStyle
(
Config
.
TabBody
,
newclip
,
&
newclip
);
}
void
CImageGUISkin
::
drawIcon
(
IGUIElement
*
element
,
EGUI_DEFAULT_ICON
icon
,
const
core
::
position2di
position
,
u32
starttime
,
u32
currenttime
,
bool
loop
,
const
core
::
rect
<
s32
>*
clip
)
{
video
::
SColor
Color
=
getColor
(
gui
::
EGDC_WINDOW_SYMBOL
);
if
(
icon
==
gui
::
EGDI_CHECK_BOX_CHECKED
)
{
if
(
Config
.
CheckBoxColor
.
getAlpha
()
>
0
)
Color
=
Config
.
CheckBoxColor
;
}
// Patch to make checkbox and radio color come from gui::EGDC_WINDOW_SYMBOL -- Madoc
if
(
icon
==
gui
::
EGDI_CHECK_BOX_CHECKED
||
icon
==
gui
::
EGDI_RADIO_BUTTON_CHECKED
)
{
FallbackSkin
->
getSpriteBank
()
->
draw2DSprite
(
FallbackSkin
->
getIcon
(
icon
),
position
,
clip
,
Color
,
starttime
,
currenttime
,
loop
,
true
);
}
else
FallbackSkin
->
drawIcon
(
element
,
icon
,
position
,
starttime
,
currenttime
,
loop
,
clip
);
}
void
CImageGUISkin
::
drawHorizontalProgressBar
(
IGUIElement
*
element
,
const
core
::
rect
<
s32
>&
rectangle
,
const
core
::
rect
<
s32
>*
clip
,
f32
filledRatio
,
video
::
SColor
fillColor
,
video
::
SColor
emptyColor
)
{
if
(
!
Config
.
ProgressBar
.
Texture
||
!
Config
.
ProgressBarFilled
.
Texture
)
{
return
;
}
// Draw empty progress bar
drawElementStyle
(
Config
.
ProgressBar
,
rectangle
,
clip
,
&
emptyColor
);
// Draw filled progress bar on top
if
(
filledRatio
<
0.0
f
)
filledRatio
=
0.0
f
;
else
if
(
filledRatio
>
1.0
f
)
filledRatio
=
1.0
f
;
if
(
filledRatio
>
0.0
f
)
{
s32
filledPixels
=
(
s32
)(
filledRatio
*
rectangle
.
getSize
().
Width
);
s32
height
=
rectangle
.
getSize
().
Height
;
core
::
rect
<
s32
>
clipRect
=
clip
?
*
clip
:
rectangle
;
if
(
filledPixels
<
height
)
{
if
(
clipRect
.
LowerRightCorner
.
X
>
rectangle
.
UpperLeftCorner
.
X
+
filledPixels
)
clipRect
.
LowerRightCorner
.
X
=
rectangle
.
UpperLeftCorner
.
X
+
filledPixels
;
filledPixels
=
height
;
}
core
::
rect
<
s32
>
filledRect
=
core
::
rect
<
s32
>
(
rectangle
.
UpperLeftCorner
.
X
,
rectangle
.
UpperLeftCorner
.
Y
,
rectangle
.
UpperLeftCorner
.
X
+
filledPixels
,
rectangle
.
LowerRightCorner
.
Y
);
drawElementStyle
(
Config
.
ProgressBarFilled
,
filledRect
,
&
clipRect
,
&
fillColor
);
}
}
void
CImageGUISkin
::
drawElementStyle
(
const
SImageGUIElementStyle
&
elem
,
const
core
::
rect
<
s32
>&
rect
,
const
core
::
rect
<
s32
>*
clip
,
video
::
SColor
*
pcolor
)
{
core
::
rect
<
s32
>
srcRect
;
core
::
rect
<
s32
>
dstRect
;
core
::
dimension2du
tsize
=
elem
.
Texture
->
getSize
();
video
::
ITexture
*
texture
=
elem
.
Texture
;
video
::
SColor
color
=
elem
.
Color
;
if
(
pcolor
)
color
=
*
pcolor
;
video
::
SColor
faceColor
=
getColor
(
EGDC_3D_FACE
);
color
.
setRed
(
(
u8
)(
color
.
getRed
()
*
faceColor
.
getRed
()
/
255
)
);
color
.
setGreen
(
(
u8
)(
color
.
getGreen
()
*
faceColor
.
getGreen
()
/
255
)
);
color
.
setBlue
(
(
u8
)(
color
.
getBlue
()
*
faceColor
.
getBlue
()
/
255
)
);
color
.
setAlpha
(
(
u8
)(
color
.
getAlpha
()
*
faceColor
.
getAlpha
()
/
255
)
);
video
::
SColor
colors
[
4
]
=
{
color
,
color
,
color
,
color
};
core
::
dimension2di
dstSize
=
rect
.
getSize
();
// Scale the border if there is insufficient room
SImageGUIElementStyle
::
SBorder
dst
=
elem
.
DstBorder
;
f32
scale
=
1.0
f
;
if
(
dstSize
.
Width
<
dst
.
Left
+
dst
.
Right
)
{
scale
=
dstSize
.
Width
/
(
f32
)(
dst
.
Left
+
dst
.
Right
);
}
if
(
dstSize
.
Height
<
dst
.
Top
+
dst
.
Bottom
)
{
f32
x
=
dstSize
.
Height
/
(
f32
)(
dst
.
Top
+
dst
.
Bottom
);
if
(
x
<
scale
)
{
scale
=
x
;
}
}
if
(
scale
<
1.0
f
)
{
dst
.
Left
=
(
s32
)(
dst
.
Left
*
scale
);
dst
.
Right
=
(
s32
)(
dst
.
Right
*
scale
);
dst
.
Top
=
(
s32
)(
dst
.
Top
*
scale
);
dst
.
Bottom
=
(
s32
)(
dst
.
Bottom
*
scale
);
}
const
SImageGUIElementStyle
::
SBorder
&
src
=
elem
.
SrcBorder
;
// Draw the top left corner
srcRect
=
core
::
rect
<
s32
>
(
0
,
0
,
src
.
Left
,
src
.
Top
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
,
rect
.
UpperLeftCorner
.
Y
,
rect
.
UpperLeftCorner
.
X
+
dst
.
Left
,
rect
.
UpperLeftCorner
.
Y
+
dst
.
Top
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the top right corner
srcRect
=
core
::
rect
<
s32
>
(
tsize
.
Width
-
src
.
Right
,
0
,
tsize
.
Width
,
src
.
Top
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
LowerRightCorner
.
X
-
dst
.
Right
,
rect
.
UpperLeftCorner
.
Y
,
rect
.
LowerRightCorner
.
X
,
rect
.
UpperLeftCorner
.
Y
+
dst
.
Top
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the top border
srcRect
=
core
::
rect
<
s32
>
(
src
.
Left
,
0
,
tsize
.
Width
-
src
.
Right
,
src
.
Top
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
+
dst
.
Left
,
rect
.
UpperLeftCorner
.
Y
,
rect
.
LowerRightCorner
.
X
-
dst
.
Right
,
rect
.
UpperLeftCorner
.
Y
+
dst
.
Top
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the left border
srcRect
=
core
::
rect
<
s32
>
(
0
,
src
.
Top
,
src
.
Left
,
tsize
.
Height
-
src
.
Bottom
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
,
rect
.
UpperLeftCorner
.
Y
+
dst
.
Top
,
rect
.
UpperLeftCorner
.
X
+
dst
.
Left
,
rect
.
LowerRightCorner
.
Y
-
dst
.
Bottom
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the right border
srcRect
=
core
::
rect
<
s32
>
(
tsize
.
Width
-
src
.
Right
,
src
.
Top
,
tsize
.
Width
,
tsize
.
Height
-
src
.
Bottom
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
LowerRightCorner
.
X
-
dst
.
Right
,
rect
.
UpperLeftCorner
.
Y
+
dst
.
Top
,
rect
.
LowerRightCorner
.
X
,
rect
.
LowerRightCorner
.
Y
-
dst
.
Bottom
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the middle section
srcRect
=
core
::
rect
<
s32
>
(
src
.
Left
,
src
.
Top
,
tsize
.
Width
-
src
.
Right
,
tsize
.
Height
-
src
.
Bottom
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
+
dst
.
Left
,
rect
.
UpperLeftCorner
.
Y
+
dst
.
Top
,
rect
.
LowerRightCorner
.
X
-
dst
.
Right
,
rect
.
LowerRightCorner
.
Y
-
dst
.
Bottom
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the bottom left corner
srcRect
=
core
::
rect
<
s32
>
(
0
,
tsize
.
Height
-
src
.
Bottom
,
src
.
Left
,
tsize
.
Height
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
,
rect
.
LowerRightCorner
.
Y
-
dst
.
Bottom
,
rect
.
UpperLeftCorner
.
X
+
dst
.
Left
,
rect
.
LowerRightCorner
.
Y
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the bottom right corner
srcRect
=
core
::
rect
<
s32
>
(
tsize
.
Width
-
src
.
Right
,
tsize
.
Height
-
src
.
Bottom
,
tsize
.
Width
,
tsize
.
Height
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
LowerRightCorner
.
X
-
dst
.
Right
,
rect
.
LowerRightCorner
.
Y
-
dst
.
Bottom
,
rect
.
LowerRightCorner
.
X
,
rect
.
LowerRightCorner
.
Y
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
// Draw the bottom border
srcRect
=
core
::
rect
<
s32
>
(
src
.
Left
,
tsize
.
Height
-
src
.
Bottom
,
tsize
.
Width
-
src
.
Right
,
tsize
.
Height
);
dstRect
=
core
::
rect
<
s32
>
(
rect
.
UpperLeftCorner
.
X
+
dst
.
Left
,
rect
.
LowerRightCorner
.
Y
-
dst
.
Bottom
,
rect
.
LowerRightCorner
.
X
-
dst
.
Right
,
rect
.
LowerRightCorner
.
Y
);
if
(
!
clip
||
clipRects
(
dstRect
,
srcRect
,
*
clip
)
)
VideoDriver
->
draw2DImage
(
texture
,
dstRect
,
srcRect
,
clip
,
colors
,
true
);
}
void
CImageGUISkin
::
draw2DRectangle
(
IGUIElement
*
element
,
const
video
::
SColor
&
color
,
const
core
::
rect
<
s32
>&
pos
,
const
core
::
rect
<
s32
>*
clip
)
{
FallbackSkin
->
draw2DRectangle
(
element
,
color
,
pos
,
clip
);
}
}
// namespace gui
}
// namespace irr
gframe/CGUISkinSystem/CImageGUISkin.h
0 → 100644
View file @
1147fb51
#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
gframe/CGUISkinSystem/clipRects.h
0 → 100644
View file @
1147fb51
#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
gframe/CXMLRegistry/CXMLNode.cpp
0 → 100644
View file @
1147fb51
#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
gframe/CXMLRegistry/CXMLNode.h
0 → 100644
View file @
1147fb51
// 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
gframe/CXMLRegistry/CXMLRegistry.cpp
0 → 100644
View file @
1147fb51
#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
gframe/CXMLRegistry/CXMLRegistry.h
0 → 100644
View file @
1147fb51
// 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
gframe/game.cpp
View file @
1147fb51
...
...
@@ -14,6 +14,7 @@
#include "duelclient.h"
#include "netserver.h"
#include "single_mode.h"
#include <sstream>
#endif //YGOPRO_SERVER_MODE
#ifndef _WIN32
...
...
@@ -96,6 +97,17 @@ bool Game::Initialize() {
device
=
irr
::
createDeviceEx
(
params
);
if
(
!
device
)
return
false
;
// Apply skin
if
(
gameConf
.
skin_index
>=
0
)
{
wchar_t
skin_dir
[
16
];
myswprintf
(
skin_dir
,
L"skin"
);
skinSystem
=
new
CGUISkinSystem
(
skin_dir
,
device
);
core
::
array
<
core
::
stringw
>
skins
=
skinSystem
->
listSkins
();
if
((
size_t
)
gameConf
.
skin_index
<
skins
.
size
())
{
int
index
=
skins
.
size
()
-
gameConf
.
skin_index
-
1
;
// reverse index
skinSystem
->
applySkin
(
skins
[
index
].
c_str
());
}
}
linePatternD3D
=
0
;
linePatternGL
=
0x0f0f
;
waitFrame
=
0
;
...
...
@@ -1173,6 +1185,7 @@ void Game::LoadConfig() {
gameConf
.
window_height
=
640
;
gameConf
.
resize_popup_menu
=
false
;
gameConf
.
chkEnablePScale
=
1
;
gameConf
.
skin_index
=
-
1
;
if
(
fp
)
{
while
(
fgets
(
linebuf
,
256
,
fp
))
{
sscanf
(
linebuf
,
"%s = %s"
,
strbuf
,
valbuf
);
...
...
@@ -1258,6 +1271,8 @@ void Game::LoadConfig() {
gameConf
.
resize_popup_menu
=
atoi
(
valbuf
)
>
0
;
}
else
if
(
!
strcmp
(
strbuf
,
"enable_pendulum_scale"
))
{
gameConf
.
chkEnablePScale
=
atoi
(
valbuf
);
}
else
if
(
!
strcmp
(
strbuf
,
"skin_index"
))
{
gameConf
.
skin_index
=
atoi
(
valbuf
);
}
else
{
// options allowing multiple words
sscanf
(
linebuf
,
"%s = %240[^
\n
]"
,
strbuf
,
valbuf
);
...
...
@@ -1361,6 +1376,8 @@ void Game::LoadConfig() {
gameConf
.
resize_popup_menu
=
atoi
(
valbuf
)
>
0
;
}
else
if
(
!
strcmp
(
strbuf
,
"enable_pendulum_scale"
))
{
gameConf
.
chkEnablePScale
=
atoi
(
valbuf
);
}
else
if
(
!
strcmp
(
strbuf
,
"skin_index"
))
{
gameConf
.
skin_index
=
atoi
(
valbuf
);
}
else
{
// options allowing multiple words
sscanf
(
linebuf
,
"%s = %240[^
\n
]"
,
strbuf
,
valbuf
);
...
...
@@ -1445,6 +1462,7 @@ void Game::SaveConfig() {
fprintf
(
fp
,
"window_height = %d
\n
"
,
gameConf
.
window_height
);
fprintf
(
fp
,
"resize_popup_menu = %d
\n
"
,
gameConf
.
resize_popup_menu
?
1
:
0
);
fprintf
(
fp
,
"enable_pendulum_scale = %d
\n
"
,
((
mainGame
->
chkEnablePScale
->
isChecked
())
?
1
:
0
));
fprintf
(
fp
,
"skin_index = %d
\n
"
,
gameConf
.
skin_index
);
fclose
(
fp
);
}
void
Game
::
ShowCardInfo
(
int
code
,
bool
resize
)
{
...
...
gframe/game.h
View file @
1147fb51
...
...
@@ -6,6 +6,7 @@
#include "client_field.h"
#include "deck_con.h"
#include "menu_handler.h"
#include "CGUISkinSystem/CGUISkinSystem.h"
#else
#include "netserver.h"
#endif //YGOPRO_SERVER_MODE
...
...
@@ -57,6 +58,7 @@ struct Config {
double
music_volume
;
int
music_mode
;
int
chkEnablePScale
;
int
skin_index
;
};
struct
DuelInfo
{
...
...
@@ -231,6 +233,8 @@ public:
irr
::
core
::
dimension2d
<
irr
::
u32
>
window_size
;
float
xScale
;
float
yScale
;
CGUISkinSystem
*
skinSystem
;
ClientField
dField
;
DeckBuilder
deckBuilder
;
...
...
system.conf
View file @
1147fb51
...
...
@@ -42,3 +42,4 @@ window_width = 1024
window_height
=
640
resize_popup_menu
=
0
enable_pendulum_scale
=
1
skin_index
= -
1
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment