aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute
diff options
context:
space:
mode:
authorEinar Johan Trøan Sømåen2012-03-06 04:26:55 +0100
committerEinar Johan Trøan Sømåen2012-06-02 12:12:27 +0200
commit5a2cf6f36ff5f8a75b1e34b00bd5444619eb4615 (patch)
tree89ae3a3f2158b780001041d54b55b8758f04b14d /engines/wintermute
parentc609c778cceeaa6a70cf147451d7d894d76e40e7 (diff)
downloadscummvm-rg350-5a2cf6f36ff5f8a75b1e34b00bd5444619eb4615.tar.gz
scummvm-rg350-5a2cf6f36ff5f8a75b1e34b00bd5444619eb4615.tar.bz2
scummvm-rg350-5a2cf6f36ff5f8a75b1e34b00bd5444619eb4615.zip
WINTERMUTE: Add the UI-classes.
Diffstat (limited to 'engines/wintermute')
-rw-r--r--engines/wintermute/AdEntity.h67
-rw-r--r--engines/wintermute/AdObject.h123
-rw-r--r--engines/wintermute/AdTalkHolder.h57
-rw-r--r--engines/wintermute/AdTypes.h93
-rw-r--r--engines/wintermute/BGame.h10
-rw-r--r--engines/wintermute/BScriptHolder.h2
-rw-r--r--engines/wintermute/PartEmitter.h136
-rw-r--r--engines/wintermute/PartForce.h54
-rw-r--r--engines/wintermute/PartParticle.h86
-rw-r--r--engines/wintermute/UIButton.cpp1043
-rw-r--r--engines/wintermute/UIButton.h79
-rw-r--r--engines/wintermute/UIEdit.cpp856
-rw-r--r--engines/wintermute/UIEdit.h71
-rw-r--r--engines/wintermute/UIEntity.cpp339
-rw-r--r--engines/wintermute/UIEntity.h58
-rw-r--r--engines/wintermute/UIObject.cpp589
-rw-r--r--engines/wintermute/UIObject.h83
-rw-r--r--engines/wintermute/UIText.cpp484
-rw-r--r--engines/wintermute/UIText.h59
-rw-r--r--engines/wintermute/UITiledImage.cpp368
-rw-r--r--engines/wintermute/UITiledImage.h62
-rw-r--r--engines/wintermute/UIWindow.cpp1309
-rw-r--r--engines/wintermute/UIWindow.h92
-rw-r--r--engines/wintermute/module.mk4
24 files changed, 6118 insertions, 6 deletions
diff --git a/engines/wintermute/AdEntity.h b/engines/wintermute/AdEntity.h
new file mode 100644
index 0000000000..b85cc123c6
--- /dev/null
+++ b/engines/wintermute/AdEntity.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_ADENTITY_H
+#define WINTERMUTE_ADENTITY_H
+
+#include "AdTalkHolder.h"
+
+namespace WinterMute {
+
+class CAdEntity : public CAdTalkHolder {
+public:
+ HRESULT SetSprite(char *Filename);
+ int m_WalkToX;
+ int m_WalkToY;
+ TDirection m_WalkToDir;
+ void SetItem(char *ItemName);
+ char *m_Item;
+ DECLARE_PERSISTENT(CAdEntity, CAdTalkHolder)
+ void UpdatePosition();
+ virtual int GetHeight();
+ CBRegion *m_Region;
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+ virtual HRESULT Update();
+ virtual HRESULT Display();
+ CAdEntity(CBGame *inGame);
+ virtual ~CAdEntity();
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ TEntityType m_Subtype;
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/AdObject.h b/engines/wintermute/AdObject.h
new file mode 100644
index 0000000000..e5cb39e6b4
--- /dev/null
+++ b/engines/wintermute/AdObject.h
@@ -0,0 +1,123 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_ADOBJECT_H
+#define WINTERMUTE_ADOBJECT_H
+
+#include "AdTypes.h"
+#include "PartEmitter.h"
+
+namespace WinterMute {
+
+class CAdWaypointGroup;
+class CAdRegion;
+class CAdSentence;
+class CBFont;
+class CBRegion;
+class CAdInventory;
+
+#define MAX_NUM_REGIONS 10
+
+class CAdObject : public CBObject {
+public:
+ CPartEmitter *m_PartEmitter;
+ virtual CPartEmitter *CreateParticleEmitter(bool FollowParent = false, int OffsetX = 0, int OffsetY = 0);
+ virtual HRESULT UpdatePartEmitter();
+ bool m_PartFollowParent;
+ int m_PartOffsetX;
+ int m_PartOffsetY;
+
+ HRESULT InvalidateCurrRegions();
+ bool m_SubtitlesModRelative;
+ bool m_SubtitlesModXCenter;
+ int m_SubtitlesModX;
+ int m_SubtitlesModY;
+ int m_SubtitlesWidth;
+ CAdRegion *m_StickRegion;
+ bool m_SceneIndependent;
+ bool m_IgnoreItems;
+ HRESULT UpdateBlockRegion();
+ bool m_ForcedTalkAnimUsed;
+ char *m_ForcedTalkAnimName;
+ virtual bool GetExtendedFlag(char *FlagName);
+ virtual HRESULT ResetSoundPan();
+ virtual HRESULT UpdateSounds();
+ HRESULT Reset();
+ DECLARE_PERSISTENT(CAdObject, CBObject)
+ virtual void Talk(char *Text, char *Sound = NULL, uint32 Duration = 0, char *Stances = NULL, TTextAlign Align = TAL_CENTER);
+ virtual int GetHeight();
+ CAdSentence *m_Sentence;
+ HRESULT SetFont(char *Filename);
+ virtual HRESULT Update();
+ virtual HRESULT Display();
+ bool m_Drawn;
+ bool m_Active;
+ virtual HRESULT PlayAnim(char *Filename);
+ CBSprite *m_AnimSprite;
+ CBSprite *m_CurrentSprite;
+ TObjectState m_State;
+ TObjectState m_NextState;
+ TObjectType m_Type;
+ CAdObject(CBGame *inGame);
+ virtual ~CAdObject();
+ CBFont *m_Font;
+ CBSprite *m_TempSprite2;
+ CBRegion *m_BlockRegion;
+ CAdWaypointGroup *m_WptGroup;
+ CBRegion *m_CurrentBlockRegion;
+ CAdWaypointGroup *m_CurrentWptGroup;
+ CAdInventory *GetInventory();
+
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ virtual HRESULT AfterMove();
+ CAdRegion *m_CurrentRegions[MAX_NUM_REGIONS];
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+
+ CBArray<CAdObject *, CAdObject *> m_AttachmentsPre;
+ CBArray<CAdObject *, CAdObject *> m_AttachmentsPost;
+
+ HRESULT UpdateSpriteAttachments();
+ HRESULT DisplaySpriteAttachments(bool PreDisplay);
+ CAdObject *m_RegisterAlias;
+private:
+ HRESULT DisplaySpriteAttachment(CAdObject *Attachment);
+ CAdInventory *m_Inventory;
+
+protected:
+ HRESULT GetScale(float *ScaleX, float *ScaleY);
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/AdTalkHolder.h b/engines/wintermute/AdTalkHolder.h
new file mode 100644
index 0000000000..7eb07a8f66
--- /dev/null
+++ b/engines/wintermute/AdTalkHolder.h
@@ -0,0 +1,57 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_ADTALKHOLDER_H
+#define WINTERMUTE_ADTALKHOLDER_H
+
+#include "AdObject.h"
+
+namespace WinterMute {
+
+class CAdTalkHolder : public CAdObject {
+public:
+ DECLARE_PERSISTENT(CAdTalkHolder, CAdObject)
+ virtual CBSprite *GetTalkStance(char *Stance);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+ CBSprite *m_Sprite;
+ CBArray<CBSprite *, CBSprite *> m_TalkSprites;
+ CBArray<CBSprite *, CBSprite *> m_TalkSpritesEx;
+ CAdTalkHolder(CBGame *inGame);
+ virtual ~CAdTalkHolder();
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/AdTypes.h b/engines/wintermute/AdTypes.h
new file mode 100644
index 0000000000..8e77f289bc
--- /dev/null
+++ b/engines/wintermute/AdTypes.h
@@ -0,0 +1,93 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_ADTYPES_H
+#define WINTERMUTE_ADTYPES_H
+
+namespace WinterMute {
+
+typedef enum {
+ GAME_NORMAL, GAME_WAITING_RESPONSE
+} TGameStateEx;
+
+
+typedef enum {
+ OBJECT_ENTITY, OBJECT_REGION, OBJECT_ACTOR, OBJECT_NONE
+} TObjectType;
+
+
+typedef enum {
+ ENTITY_NORMAL, ENTITY_SOUND
+} TEntityType;
+
+
+typedef enum {
+ STATE_NONE,
+ STATE_IDLE,
+ STATE_PLAYING_ANIM,
+ STATE_READY,
+ STATE_FOLLOWING_PATH,
+ STATE_SEARCHING_PATH,
+ STATE_WAITING_PATH,
+ STATE_TURNING_LEFT,
+ STATE_TURNING_RIGHT,
+ STATE_TURNING,
+ STATE_TALKING,
+ STATE_DIRECT_CONTROL,
+ STATE_PLAYING_ANIM_SET
+} TObjectState;
+
+typedef enum {
+ DIRECT_WALK_NONE, DIRECT_WALK_FW, DIRECT_WALK_BK
+} TDirectWalkMode;
+
+typedef enum {
+ DIRECT_TURN_NONE, DIRECT_TURN_CW, DIRECT_TURN_CCW
+} TDirectTurnMode;
+
+typedef enum {
+ RESPONSE_TEXT, RESPONSE_ICON
+} TResponseStyle;
+
+typedef enum {
+ RESPONSE_ALWAYS, RESPONSE_ONCE, RESPONSE_ONCE_GAME
+} TResponseType;
+
+
+typedef enum {
+ TALK_SKIP_LEFT = 0, TALK_SKIP_RIGHT = 1, TALK_SKIP_BOTH = 2, TALK_SKIP_NONE = 3
+} TTalkSkipButton;
+
+
+typedef enum {
+ GEOM_WAYPOINT, GEOM_WALKPLANE, GEOM_BLOCKED, GEOM_GENERIC
+} TGeomNodeType;
+
+} // end of namespace WinterMute
+
+#endif // __WmeAdTypes_H__
diff --git a/engines/wintermute/BGame.h b/engines/wintermute/BGame.h
index 2af7d834b1..a13144d325 100644
--- a/engines/wintermute/BGame.h
+++ b/engines/wintermute/BGame.h
@@ -170,10 +170,8 @@ public:
#endif
uint32 m_CurrentTime;
uint32 m_DeltaTime;
-#if 0
CBFont *m_SystemFont;
CBFont *m_VideoFont;
-#endif
HRESULT Initialize1();
HRESULT Initialize2();
HRESULT Initialize3();
@@ -265,10 +263,12 @@ public:
virtual HRESULT GetVersion(byte *VerMajor, byte *VerMinor, byte *ExtMajor, byte *ExtMinor);
#if 0
virtual bool HandleKeypress(SDL_Event *event);
+#endif
int m_FreezeLevel;
HRESULT Unfreeze();
HRESULT Freeze(bool IncludingMusic = true);
HRESULT FocusWindow(CUIWindow *Window);
+
bool m_LoadInProgress;
CUIWindow *m_FocusedWindow;
bool m_EditorForceScripts;
@@ -278,6 +278,7 @@ public:
static void AfterLoadFont(void *Font, void *Data);
static void AfterLoadScript(void *script, void *data);
static void InvalidateValues(void *Value, void *Data);
+#if 0
HRESULT LoadSettings(char *Filename);
HRESULT ResumeMusic(int Channel);
HRESULT SetMusicStartTime(int Channel, uint32 Time);
@@ -315,13 +316,14 @@ public:
uint32 m_LiveTimer;
uint32 m_LiveTimerDelta;
uint32 m_LiveTimerLast;
-#if 0
+
CBObject *m_CapturedObject;
+#if 0
POINT m_MousePos;
+#endif
bool ValidObject(CBObject *Object);
HRESULT UnregisterObject(CBObject *Object);
HRESULT RegisterObject(CBObject *Object);
-#endif
void QuickMessage(char *Text);
#if 0
void QuickMessageForm(LPSTR fmt, ...);
diff --git a/engines/wintermute/BScriptHolder.h b/engines/wintermute/BScriptHolder.h
index cece043b88..84a1e73c46 100644
--- a/engines/wintermute/BScriptHolder.h
+++ b/engines/wintermute/BScriptHolder.h
@@ -41,12 +41,10 @@ public:
CBScriptHolder(CBGame *inGame);
virtual ~CBScriptHolder();
-#if 0
virtual CScScript *InvokeMethodThread(char *MethodName);
virtual void MakeFreezable(bool Freezable);
bool CanHandleEvent(char *EventName);
virtual bool CanHandleMethod(char *EventMethod);
-#endif
HRESULT Cleanup();
HRESULT RemoveScript(CScScript *Script);
HRESULT AddScript(char *Filename);
diff --git a/engines/wintermute/PartEmitter.h b/engines/wintermute/PartEmitter.h
new file mode 100644
index 0000000000..d23b4db488
--- /dev/null
+++ b/engines/wintermute/PartEmitter.h
@@ -0,0 +1,136 @@
+/*
+This file is part of WME Lite.
+http://dead-code.org/redir.php?target=wmelite
+
+Copyright (c) 2011 Jan Nedoma
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef __WmePartEmitter_H__
+#define __WmePartEmitter_H__
+
+
+#include "BObject.h"
+#include "PartParticle.h"
+#include "PartForce.h"
+
+namespace WinterMute {
+class CBRegion;
+
+class CPartEmitter : public CBObject {
+public:
+ DECLARE_PERSISTENT(CPartEmitter, CBObject)
+
+ CPartEmitter(CBGame *inGame, CBScriptHolder *Owner);
+ virtual ~CPartEmitter(void);
+
+ int m_Width;
+ int m_Height;
+
+ int m_Angle1;
+ int m_Angle2;
+
+ float m_Rotation1;
+ float m_Rotation2;
+
+ float m_AngVelocity1;
+ float m_AngVelocity2;
+
+ float m_GrowthRate1;
+ float m_GrowthRate2;
+ bool m_ExponentialGrowth;
+
+ float m_Velocity1;
+ float m_Velocity2;
+ bool m_VelocityZBased;
+
+ float m_Scale1;
+ float m_Scale2;
+ bool m_ScaleZBased;
+
+ int m_MaxParticles;
+
+ int m_LifeTime1;
+ int m_LifeTime2;
+ bool m_LifeTimeZBased;
+
+ int m_GenInterval;
+ int m_GenAmount;
+
+ bool m_Running;
+ int m_OverheadTime;
+
+ int m_MaxBatches;
+ int m_BatchesGenerated;
+
+ RECT m_Border;
+ int m_BorderThicknessLeft;
+ int m_BorderThicknessRight;
+ int m_BorderThicknessTop;
+ int m_BorderThicknessBottom;
+
+ int m_FadeInTime;
+ int m_FadeOutTime;
+
+ int m_Alpha1;
+ int m_Alpha2;
+ bool m_AlphaTimeBased;
+
+ bool m_UseRegion;
+
+ char *m_EmitEvent;
+ CBScriptHolder *m_Owner;
+
+ HRESULT Start();
+
+ HRESULT Update();
+ HRESULT Display(CBRegion *Region = NULL);
+
+ HRESULT SortParticlesByZ();
+ HRESULT AddSprite(char *Filename);
+ HRESULT RemoveSprite(char *Filename);
+ HRESULT SetBorder(int X, int Y, int Width, int Height);
+ HRESULT SetBorderThickness(int ThicknessLeft, int ThicknessRight, int ThicknessTop, int ThicknessBottom);
+
+ HRESULT AddForce(char *Name, CPartForce::TForceType Type, int PosX, int PosY, float Angle, float Strength);
+ HRESULT RemoveForce(char *Name);
+
+ CBArray<CPartForce *, CPartForce *> m_Forces;
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+
+
+private:
+ CPartForce *AddForceByName(char *Name);
+ int static CompareZ(const void *Obj1, const void *Obj2);
+ HRESULT InitParticle(CPartParticle *Particle, uint32 CurrentTime, uint32 TimerDelta);
+ HRESULT UpdateInternal(uint32 CurrentTime, uint32 TimerDelta);
+ uint32 m_LastGenTime;
+ CBArray<CPartParticle *, CPartParticle *> m_Particles;
+ CBArray<char *, char *> m_Sprites;
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/PartForce.h b/engines/wintermute/PartForce.h
new file mode 100644
index 0000000000..140174eb4f
--- /dev/null
+++ b/engines/wintermute/PartForce.h
@@ -0,0 +1,54 @@
+/*
+This file is part of WME Lite.
+http://dead-code.org/redir.php?target=wmelite
+
+Copyright (c) 2011 Jan Nedoma
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef __WmePartForce_H__
+#define __WmePartForce_H__
+
+
+#include "BBase.h"
+#include "BNamedObject.h"
+#include "Vector2.h"
+
+namespace WinterMute {
+
+class CPartForce : public CBNamedObject {
+public:
+ enum TForceType {
+ FORCE_POINT, FORCE_GLOBAL
+ };
+
+ CPartForce(CBGame *inGame);
+ virtual ~CPartForce(void);
+
+ Vector2 m_Pos;
+ Vector2 m_Direction;
+ TForceType m_Type;
+
+ HRESULT Persist(CBPersistMgr *PersistMgr);
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/PartParticle.h b/engines/wintermute/PartParticle.h
new file mode 100644
index 0000000000..eec3862b72
--- /dev/null
+++ b/engines/wintermute/PartParticle.h
@@ -0,0 +1,86 @@
+/*
+This file is part of WME Lite.
+http://dead-code.org/redir.php?target=wmelite
+
+Copyright (c) 2011 Jan Nedoma
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef __WmePartParticle_H__
+#define __WmePartParticle_H__
+
+
+#include "BBase.h"
+#include "Vector2.h"
+
+namespace WinterMute {
+
+class CPartEmitter;
+class CBSprite;
+class CBPersistMgr;
+
+class CPartParticle : public CBBase {
+public:
+ enum TParticleState {
+ PARTICLE_NORMAL, PARTICLE_FADEIN, PARTICLE_FADEOUT
+ };
+
+ CPartParticle(CBGame *inGame);
+ virtual ~CPartParticle(void);
+
+ float m_GrowthRate;
+ bool m_ExponentialGrowth;
+
+ float m_Rotation;
+ float m_AngVelocity;
+
+ int m_Alpha1;
+ int m_Alpha2;
+
+ RECT m_Border;
+ Vector2 m_Pos;
+ float m_PosZ;
+ Vector2 m_Velocity;
+ float m_Scale;
+ CBSprite *m_Sprite;
+ uint32 m_CreationTime;
+ int m_LifeTime;
+ bool m_IsDead;
+ TParticleState m_State;
+
+ HRESULT Update(CPartEmitter *Emitter, uint32 CurrentTime, uint32 TimerDelta);
+ HRESULT Display(CPartEmitter *Emitter);
+
+ HRESULT SetSprite(char *Filename);
+
+ HRESULT FadeIn(uint32 CurrentTime, int FadeTime);
+ HRESULT FadeOut(uint32 CurrentTime, int FadeTime);
+
+ HRESULT Persist(CBPersistMgr *PersistMgr);
+private:
+ uint32 m_FadeStart;
+ int m_FadeTime;
+ int m_CurrentAlpha;
+ int m_FadeStartAlpha;
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UIButton.cpp b/engines/wintermute/UIButton.cpp
new file mode 100644
index 0000000000..1053cec166
--- /dev/null
+++ b/engines/wintermute/UIButton.cpp
@@ -0,0 +1,1043 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/BDynBuffer.h"
+#include "engines/wintermute/BGame.h"
+#include "engines/wintermute/UIButton.h"
+#include "engines/wintermute/UITiledImage.h"
+#include "engines/wintermute/BParser.h"
+#include "engines/wintermute/BActiveRect.h"
+#include "engines/wintermute/BFontStorage.h"
+#include "engines/wintermute/BFont.h"
+#include "engines/wintermute/BStringTable.h"
+#include "engines/wintermute/BSprite.h"
+#include "engines/wintermute/BFileManager.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/scriptables/ScValue.h"
+#include "engines/wintermute/scriptables/ScScript.h"
+#include "engines/wintermute/scriptables/ScStack.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIButton, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIButton::CUIButton(CBGame *inGame): CUIObject(inGame) {
+ m_BackPress = m_BackHover = m_BackDisable = m_BackFocus = NULL;
+
+ m_FontHover = m_FontPress = m_FontDisable = m_FontFocus = NULL;
+
+ m_ImageDisable = m_ImagePress = m_ImageHover = m_ImageFocus = NULL;
+
+ m_Align = TAL_CENTER;
+
+ m_Hover = m_Press = false;
+
+ m_Type = UI_BUTTON;
+
+ m_CanFocus = false;
+ m_StayPressed = false;
+
+ m_OneTimePress = false;
+ m_CenterImage = false;
+
+ m_PixelPerfect = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIButton::~CUIButton() {
+ if (m_BackPress) delete m_BackPress;
+ if (m_BackHover) delete m_BackHover;
+ if (m_BackDisable) delete m_BackDisable;
+ if (m_BackFocus) delete m_BackFocus;
+
+ if (!m_SharedFonts) {
+ if (m_FontHover) Game->m_FontStorage->RemoveFont(m_FontHover);
+ if (m_FontPress) Game->m_FontStorage->RemoveFont(m_FontPress);
+ if (m_FontDisable) Game->m_FontStorage->RemoveFont(m_FontDisable);
+ if (m_FontFocus) Game->m_FontStorage->RemoveFont(m_FontFocus);
+ }
+
+ if (!m_SharedImages) {
+ if (m_ImageHover) delete m_ImageHover;
+ if (m_ImagePress) delete m_ImagePress;
+ if (m_ImageDisable) delete m_ImageDisable;
+ if (m_ImageFocus) delete m_ImageFocus;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::LoadFile(char *Filename) {
+ byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIButton::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ m_Filename = new char [strlen(Filename) + 1];
+ strcpy(m_Filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing BUTTON file '%s'", Filename);
+
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(BUTTON)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(FOCUSABLE)
+TOKEN_DEF(BACK_HOVER)
+TOKEN_DEF(BACK_PRESS)
+TOKEN_DEF(BACK_DISABLE)
+TOKEN_DEF(BACK_FOCUS)
+TOKEN_DEF(BACK)
+TOKEN_DEF(CENTER_IMAGE)
+TOKEN_DEF(IMAGE_HOVER)
+TOKEN_DEF(IMAGE_PRESS)
+TOKEN_DEF(IMAGE_DISABLE)
+TOKEN_DEF(IMAGE_FOCUS)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT_HOVER)
+TOKEN_DEF(FONT_PRESS)
+TOKEN_DEF(FONT_DISABLE)
+TOKEN_DEF(FONT_FOCUS)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TEXT_ALIGN)
+TOKEN_DEF(TEXT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(NAME)
+TOKEN_DEF(EVENTS)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(PRESSED)
+TOKEN_DEF(PIXEL_PERFECT)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(BUTTON)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(FOCUSABLE)
+ TOKEN_TABLE(BACK_HOVER)
+ TOKEN_TABLE(BACK_PRESS)
+ TOKEN_TABLE(BACK_DISABLE)
+ TOKEN_TABLE(BACK_FOCUS)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(CENTER_IMAGE)
+ TOKEN_TABLE(IMAGE_HOVER)
+ TOKEN_TABLE(IMAGE_PRESS)
+ TOKEN_TABLE(IMAGE_DISABLE)
+ TOKEN_TABLE(IMAGE_FOCUS)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT_HOVER)
+ TOKEN_TABLE(FONT_PRESS)
+ TOKEN_TABLE(FONT_DISABLE)
+ TOKEN_TABLE(FONT_FOCUS)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TEXT_ALIGN)
+ TOKEN_TABLE(TEXT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(EVENTS)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(PRESSED)
+ TOKEN_TABLE(PIXEL_PERFECT)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_BUTTON) {
+ Game->LOG(0, "'BUTTON' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete m_Back;
+ m_Back = new CUITiledImage(Game);
+ if (!m_Back || FAILED(m_Back->LoadFile((char *)params))) {
+ delete m_Back;
+ m_Back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_HOVER:
+ delete m_BackHover;
+ m_BackHover = new CUITiledImage(Game);
+ if (!m_BackHover || FAILED(m_BackHover->LoadFile((char *)params))) {
+ delete m_BackHover;
+ m_BackHover = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_PRESS:
+ delete m_BackPress;
+ m_BackPress = new CUITiledImage(Game);
+ if (!m_BackPress || FAILED(m_BackPress->LoadFile((char *)params))) {
+ delete m_BackPress;
+ m_BackPress = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_DISABLE:
+ delete m_BackDisable;
+ m_BackDisable = new CUITiledImage(Game);
+ if (!m_BackDisable || FAILED(m_BackDisable->LoadFile((char *)params))) {
+ delete m_BackDisable;
+ m_BackDisable = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_FOCUS:
+ delete m_BackFocus;
+ m_BackFocus = new CUITiledImage(Game);
+ if (!m_BackFocus || FAILED(m_BackFocus->LoadFile((char *)params))) {
+ delete m_BackFocus;
+ m_BackFocus = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete m_Image;
+ m_Image = new CBSprite(Game);
+ if (!m_Image || FAILED(m_Image->LoadFile((char *)params))) {
+ delete m_Image;
+ m_Image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_HOVER:
+ delete m_ImageHover;
+ m_ImageHover = new CBSprite(Game);
+ if (!m_ImageHover || FAILED(m_ImageHover->LoadFile((char *)params))) {
+ delete m_ImageHover;
+ m_ImageHover = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_PRESS:
+ delete m_ImagePress;
+ m_ImagePress = new CBSprite(Game);
+ if (!m_ImagePress || FAILED(m_ImagePress->LoadFile((char *)params))) {
+ delete m_ImagePress;
+ m_ImagePress = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_DISABLE:
+ delete m_ImageDisable;
+ m_ImageDisable = new CBSprite(Game);
+ if (!m_ImageDisable || FAILED(m_ImageDisable->LoadFile((char *)params))) {
+ delete m_ImageDisable;
+ m_ImageDisable = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_FOCUS:
+ delete m_ImageFocus;
+ m_ImageFocus = new CBSprite(Game);
+ if (!m_ImageFocus || FAILED(m_ImageFocus->LoadFile((char *)params))) {
+ delete m_ImageFocus;
+ m_ImageFocus = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
+ m_Font = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_Font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_HOVER:
+ if (m_FontHover) Game->m_FontStorage->RemoveFont(m_FontHover);
+ m_FontHover = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_FontHover) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_PRESS:
+ if (m_FontPress) Game->m_FontStorage->RemoveFont(m_FontPress);
+ m_FontPress = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_FontPress) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_DISABLE:
+ if (m_FontDisable) Game->m_FontStorage->RemoveFont(m_FontDisable);
+ m_FontDisable = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_FontDisable) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_FOCUS:
+ if (m_FontFocus) Game->m_FontStorage->RemoveFont(m_FontFocus);
+ m_FontFocus = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_FontFocus) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TEXT:
+ SetText((char *)params);
+ Game->m_StringTable->Expand(&m_Text);
+ break;
+
+ case TOKEN_TEXT_ALIGN:
+ if (scumm_stricmp((char *)params, "left") == 0) m_Align = TAL_LEFT;
+ else if (scumm_stricmp((char *)params, "right") == 0) m_Align = TAL_RIGHT;
+ else m_Align = TAL_CENTER;
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &m_PosX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &m_PosY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &m_Width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &m_Height);
+ break;
+
+ case TOKEN_CURSOR:
+ delete m_Cursor;
+ m_Cursor = new CBSprite(Game);
+ if (!m_Cursor || FAILED(m_Cursor->LoadFile((char *)params))) {
+ delete m_Cursor;
+ m_Cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &m_ParentNotify);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &m_Disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &m_Visible);
+ break;
+
+ case TOKEN_FOCUSABLE:
+ parser.ScanStr((char *)params, "%b", &m_CanFocus);
+ break;
+
+ case TOKEN_CENTER_IMAGE:
+ parser.ScanStr((char *)params, "%b", &m_CenterImage);
+ break;
+
+ case TOKEN_PRESSED:
+ parser.ScanStr((char *)params, "%b", &m_StayPressed);
+ break;
+
+ case TOKEN_PIXEL_PERFECT:
+ parser.ScanStr((char *)params, "%b", &m_PixelPerfect);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in BUTTON definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading BUTTON definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "BUTTON\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Back && m_Back->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", m_Back->m_Filename);
+ if (m_BackHover && m_BackHover->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_HOVER=\"%s\"\n", m_BackHover->m_Filename);
+ if (m_BackPress && m_BackPress->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_PRESS=\"%s\"\n", m_BackPress->m_Filename);
+ if (m_BackDisable && m_BackDisable->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_DISABLE=\"%s\"\n", m_BackDisable->m_Filename);
+ if (m_BackFocus && m_BackFocus->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_FOCUS=\"%s\"\n", m_BackFocus->m_Filename);
+
+ if (m_Image && m_Image->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", m_Image->m_Filename);
+ if (m_ImageHover && m_ImageHover->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_HOVER=\"%s\"\n", m_ImageHover->m_Filename);
+ if (m_ImagePress && m_ImagePress->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_PRESS=\"%s\"\n", m_ImagePress->m_Filename);
+ if (m_ImageDisable && m_ImageDisable->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_DISABLE=\"%s\"\n", m_ImageDisable->m_Filename);
+ if (m_ImageFocus && m_ImageFocus->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_FOCUS=\"%s\"\n", m_ImageFocus->m_Filename);
+
+ if (m_Font && m_Font->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", m_Font->m_Filename);
+ if (m_FontHover && m_FontHover->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_HOVER=\"%s\"\n", m_FontHover->m_Filename);
+ if (m_FontPress && m_FontPress->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_PRESS=\"%s\"\n", m_FontPress->m_Filename);
+ if (m_FontDisable && m_FontDisable->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_DISABLE=\"%s\"\n", m_FontDisable->m_Filename);
+ if (m_FontFocus && m_FontFocus->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_FOCUS=\"%s\"\n", m_FontFocus->m_Filename);
+
+ if (m_Cursor && m_Cursor->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", m_Cursor->m_Filename);
+
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Text)
+ Buffer->PutTextIndent(Indent + 2, "TEXT=\"%s\"\n", m_Text);
+
+ switch (m_Align) {
+ case TAL_LEFT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "left");
+ break;
+ case TAL_RIGHT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "right");
+ break;
+ case TAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "center");
+ break;
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", m_PosX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", m_PosY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", m_Width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", m_Height);
+
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", m_Disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", m_Visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", m_ParentNotify ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "FOCUSABLE=%s\n", m_CanFocus ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "CENTER_IMAGE=%s\n", m_CenterImage ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PRESSED=%s\n", m_StayPressed ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PIXEL_PERFECT=%s\n", m_PixelPerfect ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < m_Scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CUIButton::CorrectSize() {
+ RECT rect;
+
+ CBSprite *img = NULL;
+ if (m_Image) img = m_Image;
+ else if (m_ImageDisable) img = m_ImageDisable;
+ else if (m_ImageHover) img = m_ImageHover;
+ else if (m_ImagePress) img = m_ImagePress;
+ else if (m_ImageFocus) img = m_ImageFocus;
+
+ if (m_Width <= 0) {
+ if (img) {
+ img->GetBoundingRect(&rect, 0, 0);
+ m_Width = rect.right - rect.left;
+ } else m_Width = 100;
+ }
+
+ if (m_Height <= 0) {
+ if (img) {
+ img->GetBoundingRect(&rect, 0, 0);
+ m_Height = rect.bottom - rect.top;
+ }
+ }
+
+ if (m_Text) {
+ int text_height;
+ if (m_Font) text_height = m_Font->GetTextHeight((byte *)m_Text, m_Width);
+ else text_height = Game->m_SystemFont->GetTextHeight((byte *)m_Text, m_Width);
+
+ if (text_height > m_Height) m_Height = text_height;
+ }
+
+ if (m_Height <= 0) m_Height = 100;
+
+ if (m_Back) m_Back->CorrectSize(&m_Width, &m_Height);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::Display(int OffsetX, int OffsetY) {
+ if (!m_Visible) return S_OK;
+
+ CUITiledImage *back = NULL;
+ CBSprite *image = NULL;
+ CBFont *font = 0;
+
+ //RECT rect;
+ //CBPlatform::SetRect(&rect, OffsetX + m_PosX, OffsetY + m_PosY, OffsetX+m_PosX+m_Width, OffsetY+m_PosY+m_Height);
+ //m_Hover = (!m_Disable && CBPlatform::PtInRect(&rect, Game->m_MousePos)!=FALSE);
+ m_Hover = (!m_Disable && Game->m_ActiveObject == this && (Game->m_Interactive || Game->m_State == GAME_SEMI_FROZEN));
+
+ if ((m_Press && m_Hover && !Game->m_MouseLeftDown) ||
+ m_OneTimePress && CBPlatform::GetTime() - m_OneTimePressTime >= 100) Press();
+
+
+ if (m_Disable) {
+ if (m_BackDisable) back = m_BackDisable;
+ if (m_ImageDisable) image = m_ImageDisable;
+ if (m_Text && m_FontDisable) font = m_FontDisable;
+ } else if (m_Press || m_OneTimePress || m_StayPressed) {
+ if (m_BackPress) back = m_BackPress;
+ if (m_ImagePress) image = m_ImagePress;
+ if (m_Text && m_FontPress) font = m_FontPress;
+ } else if (m_Hover) {
+ if (m_BackHover) back = m_BackHover;
+ if (m_ImageHover) image = m_ImageHover;
+ if (m_Text && m_FontHover) font = m_FontHover;
+ } else if (m_CanFocus && IsFocused()) {
+ if (m_BackFocus) back = m_BackFocus;
+ if (m_ImageFocus) image = m_ImageFocus;
+ if (m_Text && m_FontFocus) font = m_FontFocus;
+ }
+
+ if (!back && m_Back) back = m_Back;
+ if (!image && m_Image) image = m_Image;
+ if (m_Text && !font) {
+ if (m_Font) font = m_Font;
+ else font = Game->m_SystemFont;
+ }
+
+ int ImageX = OffsetX + m_PosX;
+ int ImageY = OffsetY + m_PosY;
+
+ if (image && m_CenterImage) {
+ RECT rc;
+ image->GetBoundingRect(&rc, 0, 0);
+ ImageX += (m_Width - (rc.right - rc.left)) / 2;
+ ImageY += (m_Height - (rc.bottom - rc.top)) / 2;
+ }
+
+ if (back) back->Display(OffsetX + m_PosX, OffsetY + m_PosY, m_Width, m_Height);
+ //if(image) image->Draw(ImageX +((m_Press||m_OneTimePress)&&back?1:0), ImageY +((m_Press||m_OneTimePress)&&back?1:0), NULL);
+ if (image) image->Draw(ImageX + ((m_Press || m_OneTimePress) && back ? 1 : 0), ImageY + ((m_Press || m_OneTimePress) && back ? 1 : 0), m_PixelPerfect ? this : NULL);
+
+ if (font && m_Text) {
+ int text_offset = (m_Height - font->GetTextHeight((byte *)m_Text, m_Width)) / 2;
+ font->DrawText((byte *)m_Text, OffsetX + m_PosX + ((m_Press || m_OneTimePress) ? 1 : 0), OffsetY + m_PosY + text_offset + ((m_Press || m_OneTimePress) ? 1 : 0), m_Width, m_Align);
+ }
+
+ if (!m_PixelPerfect || !m_Image) Game->m_Renderer->m_RectList.Add(new CBActiveRect(Game, this, NULL, OffsetX + m_PosX, OffsetY + m_PosY, m_Width, m_Height, 100, 100, false));
+
+ // reset unused sprites
+ if (m_Image && m_Image != image) m_Image->Reset();
+ if (m_ImageDisable && m_ImageDisable != image) m_ImageDisable->Reset();
+ if (m_ImageFocus && m_ImageFocus != image) m_ImageFocus->Reset();
+ if (m_ImagePress && m_ImagePress != image) m_ImagePress->Reset();
+ if (m_ImageHover && m_ImageHover != image) m_ImageHover->Reset();
+
+ m_Press = m_Hover && Game->m_MouseLeftDown && Game->m_CapturedObject == this;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIButton::Press() {
+ ApplyEvent("Press");
+ if (m_ListenerObject) m_ListenerObject->Listen(m_ListenerParamObject, m_ListenerParamDWORD);
+ if (m_ParentNotify && m_Parent) m_Parent->ApplyEvent(m_Name);
+
+ m_OneTimePress = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetDisabledFont
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SetDisabledFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (m_FontDisable) Game->m_FontStorage->RemoveFont(m_FontDisable);
+ if (Val->IsNULL()) {
+ m_FontDisable = NULL;
+ Stack->PushBool(true);
+ } else {
+ m_FontDisable = Game->m_FontStorage->AddFont(Val->GetString());
+ Stack->PushBool(m_FontDisable != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetHoverFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetHoverFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (m_FontHover) Game->m_FontStorage->RemoveFont(m_FontHover);
+ if (Val->IsNULL()) {
+ m_FontHover = NULL;
+ Stack->PushBool(true);
+ } else {
+ m_FontHover = Game->m_FontStorage->AddFont(Val->GetString());
+ Stack->PushBool(m_FontHover != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPressedFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetPressedFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (m_FontPress) Game->m_FontStorage->RemoveFont(m_FontPress);
+ if (Val->IsNULL()) {
+ m_FontPress = NULL;
+ Stack->PushBool(true);
+ } else {
+ m_FontPress = Game->m_FontStorage->AddFont(Val->GetString());
+ Stack->PushBool(m_FontPress != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetFocusedFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetFocusedFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (m_FontFocus) Game->m_FontStorage->RemoveFont(m_FontFocus);
+ if (Val->IsNULL()) {
+ m_FontFocus = NULL;
+ Stack->PushBool(true);
+ } else {
+ m_FontFocus = Game->m_FontStorage->AddFont(Val->GetString());
+ Stack->PushBool(m_FontFocus != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetDisabledImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetDisabledImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete m_ImageDisable;
+ m_ImageDisable = new CBSprite(Game);
+ char *Filename = Stack->Pop()->GetString();
+ if (!m_ImageDisable || FAILED(m_ImageDisable->LoadFile(Filename))) {
+ delete m_ImageDisable;
+ m_ImageDisable = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetDisabledImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetDisabledImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageDisable || !m_ImageDisable->m_Filename) Stack->PushNULL();
+ else Stack->PushString(m_ImageDisable->m_Filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetDisabledImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetDisabledImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageDisable) Stack->PushNULL();
+ else Stack->PushNative(m_ImageDisable, true);
+
+ return S_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetHoverImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetHoverImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete m_ImageHover;
+ m_ImageHover = new CBSprite(Game);
+ char *Filename = Stack->Pop()->GetString();
+ if (!m_ImageHover || FAILED(m_ImageHover->LoadFile(Filename))) {
+ delete m_ImageHover;
+ m_ImageHover = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetHoverImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetHoverImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageHover || !m_ImageHover->m_Filename) Stack->PushNULL();
+ else Stack->PushString(m_ImageHover->m_Filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetHoverImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetHoverImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageHover) Stack->PushNULL();
+ else Stack->PushNative(m_ImageHover, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPressedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetPressedImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete m_ImagePress;
+ m_ImagePress = new CBSprite(Game);
+ char *Filename = Stack->Pop()->GetString();
+ if (!m_ImagePress || FAILED(m_ImagePress->LoadFile(Filename))) {
+ delete m_ImagePress;
+ m_ImagePress = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetPressedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetPressedImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImagePress || !m_ImagePress->m_Filename) Stack->PushNULL();
+ else Stack->PushString(m_ImagePress->m_Filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetPressedImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetPressedImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImagePress) Stack->PushNULL();
+ else Stack->PushNative(m_ImagePress, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetFocusedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetFocusedImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete m_ImageFocus;
+ m_ImageFocus = new CBSprite(Game);
+ char *Filename = Stack->Pop()->GetString();
+ if (!m_ImageFocus || FAILED(m_ImageFocus->LoadFile(Filename))) {
+ delete m_ImageFocus;
+ m_ImageFocus = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFocusedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetFocusedImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageFocus || !m_ImageFocus->m_Filename) Stack->PushNULL();
+ else Stack->PushString(m_ImageFocus->m_Filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFocusedImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetFocusedImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageFocus) Stack->PushNULL();
+ else Stack->PushNative(m_ImageFocus, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Press
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Press") == 0) {
+ Stack->CorrectParams(0);
+
+ if (m_Visible && !m_Disable) {
+ m_OneTimePress = true;
+ m_OneTimePressTime = CBPlatform::GetTime();
+ }
+ Stack->PushNULL();
+
+ return S_OK;
+ }
+
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIButton::ScGetProperty(char *Name) {
+ m_ScValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ m_ScValue->SetString("button");
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "TextAlign") == 0) {
+ m_ScValue->SetInt(m_Align);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Focusable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Focusable") == 0) {
+ m_ScValue->SetBool(m_CanFocus);
+ return m_ScValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Pressed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Pressed") == 0) {
+ m_ScValue->SetBool(m_StayPressed);
+ return m_ScValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // PixelPerfect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PixelPerfect") == 0) {
+ m_ScValue->SetBool(m_PixelPerfect);
+ return m_ScValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::ScSetProperty(char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "TextAlign") == 0) {
+ int i = Value->GetInt();
+ if (i < 0 || i >= NUM_TEXT_ALIGN) i = 0;
+ m_Align = (TTextAlign)i;
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Focusable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Focusable") == 0) {
+ m_CanFocus = Value->GetBool();
+ return S_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Pressed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Pressed") == 0) {
+ m_StayPressed = Value->GetBool();
+ return S_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // PixelPerfect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PixelPerfect") == 0) {
+ m_PixelPerfect = Value->GetBool();
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CUIButton::ScToString() {
+ return "[button]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER_INT(m_Align));
+ PersistMgr->Transfer(TMEMBER(m_BackDisable));
+ PersistMgr->Transfer(TMEMBER(m_BackFocus));
+ PersistMgr->Transfer(TMEMBER(m_BackHover));
+ PersistMgr->Transfer(TMEMBER(m_BackPress));
+ PersistMgr->Transfer(TMEMBER(m_CenterImage));
+ PersistMgr->Transfer(TMEMBER(m_FontDisable));
+ PersistMgr->Transfer(TMEMBER(m_FontFocus));
+ PersistMgr->Transfer(TMEMBER(m_FontHover));
+ PersistMgr->Transfer(TMEMBER(m_FontPress));
+ PersistMgr->Transfer(TMEMBER(m_Hover));
+ PersistMgr->Transfer(TMEMBER(m_Image));
+ PersistMgr->Transfer(TMEMBER(m_ImageDisable));
+ PersistMgr->Transfer(TMEMBER(m_ImageFocus));
+ PersistMgr->Transfer(TMEMBER(m_ImageHover));
+ PersistMgr->Transfer(TMEMBER(m_ImagePress));
+ PersistMgr->Transfer(TMEMBER(m_PixelPerfect));
+ PersistMgr->Transfer(TMEMBER(m_Press));
+ PersistMgr->Transfer(TMEMBER(m_StayPressed));
+
+ if (!PersistMgr->m_Saving) {
+ m_OneTimePress = false;
+ m_OneTimePressTime = 0;
+ }
+
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UIButton.h b/engines/wintermute/UIButton.h
new file mode 100644
index 0000000000..aa4b7f8b78
--- /dev/null
+++ b/engines/wintermute/UIButton.h
@@ -0,0 +1,79 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIBUTTON_H
+#define WINTERMUTE_UIBUTTON_H
+
+
+#include "UIObject.h"
+#include "dctypes.h" // Added by ClassView
+
+namespace WinterMute {
+
+class CUIButton : public CUIObject {
+public:
+ bool m_PixelPerfect;
+ bool m_StayPressed;
+ bool m_CenterImage;
+ bool m_OneTimePress;
+ uint32 m_OneTimePressTime;
+ DECLARE_PERSISTENT(CUIButton, CUIObject)
+ void Press();
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ bool m_Press;
+ bool m_Hover;
+ void CorrectSize();
+ TTextAlign m_Align;
+ CBSprite *m_ImageHover;
+ CBSprite *m_ImagePress;
+ CBSprite *m_ImageDisable;
+ CBSprite *m_ImageFocus;
+ CBFont *m_FontDisable;
+ CBFont *m_FontPress;
+ CBFont *m_FontHover;
+ CBFont *m_FontFocus;
+ CUITiledImage *m_BackPress;
+ CUITiledImage *m_BackHover;
+ CUITiledImage *m_BackDisable;
+ CUITiledImage *m_BackFocus;
+ CUIButton(CBGame *inGame = NULL);
+ virtual ~CUIButton();
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UIEdit.cpp b/engines/wintermute/UIEdit.cpp
new file mode 100644
index 0000000000..af214c50dd
--- /dev/null
+++ b/engines/wintermute/UIEdit.cpp
@@ -0,0 +1,856 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/UIEdit.h"
+#include "engines/wintermute/UIObject.h"
+#include "engines/wintermute/UITiledImage.h"
+#include "engines/wintermute/StringUtil.h"
+#include "engines/wintermute/BActiveRect.h"
+#include "engines/wintermute/BFileManager.h"
+#include "engines/wintermute/BFont.h"
+#include "engines/wintermute/BFontStorage.h"
+#include "engines/wintermute/BKeyboardState.h"
+#include "engines/wintermute/BDynBuffer.h"
+#include "engines/wintermute/BParser.h"
+#include "engines/wintermute/BSprite.h"
+#include "engines/wintermute/BStringTable.h"
+#include "engines/wintermute/BGame.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/scriptables/ScValue.h"
+#include "engines/wintermute/scriptables/ScStack.h"
+#include "engines/wintermute/scriptables/ScScript.h"
+#include "engines/wintermute/utils.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIEdit, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIEdit::CUIEdit(CBGame *inGame): CUIObject(inGame) {
+ m_Type = UI_EDIT;
+
+ m_FontSelected = NULL;
+
+ m_SelStart = m_SelEnd = 10000;
+ m_ScrollOffset = 0;
+
+ m_CursorChar = NULL;
+ SetCursorChar("|");
+
+#ifdef __WIN32__
+ m_CursorBlinkRate = GetCaretBlinkTime();
+#else
+ m_CursorBlinkRate = 600;
+#endif
+ m_FrameWidth = 0;
+
+ SetText("");
+
+ m_LastBlinkTime = 0;
+ m_CursorVisible = true;
+
+ m_MaxLength = -1;
+
+ m_CanFocus = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIEdit::~CUIEdit() {
+ if (!m_SharedFonts) {
+ if (m_FontSelected) Game->m_FontStorage->RemoveFont(m_FontSelected);
+ }
+
+ delete[] m_CursorChar;
+ m_CursorChar = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::LoadFile(char *Filename) {
+ byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIEdit::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ m_Filename = new char [strlen(Filename) + 1];
+ strcpy(m_Filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing EDIT file '%s'", Filename);
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(BACK)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT_SELECTED)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TEXT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(CURSOR_BLINK_RATE)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(FRAME_WIDTH)
+TOKEN_DEF(NAME)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(MAX_LENGTH)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(EDIT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT_SELECTED)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TEXT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(CURSOR_BLINK_RATE)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(FRAME_WIDTH)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(MAX_LENGTH)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(EDIT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_EDIT) {
+ Game->LOG(0, "'EDIT' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete m_Back;
+ m_Back = new CUITiledImage(Game);
+ if (!m_Back || FAILED(m_Back->LoadFile((char *)params))) {
+ delete m_Back;
+ m_Back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete m_Image;
+ m_Image = new CBSprite(Game);
+ if (!m_Image || FAILED(m_Image->LoadFile((char *)params))) {
+ delete m_Image;
+ m_Image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
+ m_Font = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_Font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_SELECTED:
+ if (m_FontSelected) Game->m_FontStorage->RemoveFont(m_FontSelected);
+ m_FontSelected = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_FontSelected) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TEXT:
+ SetText((char *)params);
+ Game->m_StringTable->Expand(&m_Text);
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &m_PosX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &m_PosY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &m_Width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &m_Height);
+ break;
+
+ case TOKEN_MAX_LENGTH:
+ parser.ScanStr((char *)params, "%d", &m_MaxLength);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_CURSOR:
+ delete m_Cursor;
+ m_Cursor = new CBSprite(Game);
+ if (!m_Cursor || FAILED(m_Cursor->LoadFile((char *)params))) {
+ delete m_Cursor;
+ m_Cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_CURSOR_BLINK_RATE:
+ parser.ScanStr((char *)params, "%d", &m_CursorBlinkRate);
+ break;
+
+ case TOKEN_FRAME_WIDTH:
+ parser.ScanStr((char *)params, "%d", &m_FrameWidth);
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &m_ParentNotify);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &m_Disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &m_Visible);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in EDIT definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading EDIT definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "EDIT\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Back && m_Back->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", m_Back->m_Filename);
+
+ if (m_Image && m_Image->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", m_Image->m_Filename);
+
+ if (m_Font && m_Font->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", m_Font->m_Filename);
+ if (m_FontSelected && m_FontSelected->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_SELECTED=\"%s\"\n", m_FontSelected->m_Filename);
+
+ if (m_Cursor && m_Cursor->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", m_Cursor->m_Filename);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Text)
+ Buffer->PutTextIndent(Indent + 2, "TEXT=\"%s\"\n", m_Text);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", m_PosX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", m_PosY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", m_Width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", m_Height);
+ Buffer->PutTextIndent(Indent + 2, "MAX_LENGTH=%d\n", m_MaxLength);
+ Buffer->PutTextIndent(Indent + 2, "CURSOR_BLINK_RATE=%d\n", m_CursorBlinkRate);
+ Buffer->PutTextIndent(Indent + 2, "FRAME_WIDTH=%d\n", m_FrameWidth);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", m_Disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", m_Visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", m_ParentNotify ? "TRUE" : "FALSE");
+
+ // scripts
+ for (int i = 0; i < m_Scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetSelectedFont
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SetSelectedFont") == 0) {
+ Stack->CorrectParams(1);
+
+ if (m_FontSelected) Game->m_FontStorage->RemoveFont(m_FontSelected);
+ m_FontSelected = Game->m_FontStorage->AddFont(Stack->Pop()->GetString());
+ Stack->PushBool(m_FontSelected != NULL);
+
+ return S_OK;
+ }
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIEdit::ScGetProperty(char *Name) {
+ m_ScValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ m_ScValue->SetString("editor");
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SelStart
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SelStart") == 0) {
+ m_ScValue->SetInt(m_SelStart);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SelEnd
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SelEnd") == 0) {
+ m_ScValue->SetInt(m_SelEnd);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorBlinkRate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorBlinkRate") == 0) {
+ m_ScValue->SetInt(m_CursorBlinkRate);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorChar
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorChar") == 0) {
+ m_ScValue->SetString(m_CursorChar);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FrameWidth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FrameWidth") == 0) {
+ m_ScValue->SetInt(m_FrameWidth);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxLength
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MaxLength") == 0) {
+ m_ScValue->SetInt(m_MaxLength);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ if (Game->m_TextEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::AnsiToWide(m_Text);
+ m_ScValue->SetString(StringUtil::WideToUtf8(wstr).c_str());
+ } else {
+ m_ScValue->SetString(m_Text);
+ }
+ return m_ScValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::ScSetProperty(char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // SelStart
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SelStart") == 0) {
+ m_SelStart = Value->GetInt();
+ m_SelStart = MAX(m_SelStart, 0);
+ m_SelStart = MIN(m_SelStart, strlen(m_Text));
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SelEnd
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SelEnd") == 0) {
+ m_SelEnd = Value->GetInt();
+ m_SelEnd = MAX(m_SelEnd, 0);
+ m_SelEnd = MIN(m_SelEnd, strlen(m_Text));
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorBlinkRate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorBlinkRate") == 0) {
+ m_CursorBlinkRate = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorChar
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorChar") == 0) {
+ SetCursorChar(Value->GetString());
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FrameWidth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FrameWidth") == 0) {
+ m_FrameWidth = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxLength
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MaxLength") == 0) {
+ m_MaxLength = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ if (Game->m_TextEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::Utf8ToWide(Value->GetString());
+ SetText(StringUtil::WideToAnsi(wstr).c_str());
+ } else {
+ SetText(Value->GetString());
+ }
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CUIEdit::ScToString() {
+ return "[edit]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIEdit::SetCursorChar(char *Char) {
+ if (!Char) return;
+ delete[] m_CursorChar;
+ m_CursorChar = new char [strlen(Char) + 1];
+ if (m_CursorChar) strcpy(m_CursorChar, Char);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::Display(int OffsetX, int OffsetY) {
+ if (!m_Visible) return S_OK;
+
+
+ // hack!
+ TTextEncoding OrigEncoding = Game->m_TextEncoding;
+ Game->m_TextEncoding = TEXT_ANSI;
+
+ if (m_Back) m_Back->Display(OffsetX + m_PosX, OffsetY + m_PosY, m_Width, m_Height);
+ if (m_Image) m_Image->Draw(OffsetX + m_PosX, OffsetY + m_PosY, NULL);
+
+ // prepare fonts
+ CBFont *font;
+ CBFont *sfont;
+
+ if (m_Font) font = m_Font;
+ else font = Game->m_SystemFont;
+
+ if (m_FontSelected) sfont = m_FontSelected;
+ else sfont = font;
+
+ bool focused = IsFocused();
+
+ m_SelStart = MAX(m_SelStart, 0);
+ m_SelEnd = MAX(m_SelEnd, 0);
+
+ m_SelStart = MIN(m_SelStart, strlen(m_Text));
+ m_SelEnd = MIN(m_SelEnd, strlen(m_Text));
+
+ //int CursorWidth = font->GetCharWidth(m_CursorChar[0]);
+ int CursorWidth = font->GetTextWidth((byte *)m_CursorChar);
+
+ int s1, s2;
+ bool CurFirst;
+ // modify scroll offset
+ if (m_SelStart >= m_SelEnd) {
+ while (font->GetTextWidth((byte *)m_Text + m_ScrollOffset, std::max(0, m_SelEnd - m_ScrollOffset)) > m_Width - CursorWidth - 2 * m_FrameWidth) {
+ m_ScrollOffset++;
+ if (m_ScrollOffset >= strlen(m_Text)) break;
+ }
+
+ m_ScrollOffset = std::min(m_ScrollOffset, m_SelEnd);
+
+ s1 = m_SelEnd;
+ s2 = m_SelStart;
+ CurFirst = true;
+ } else {
+ while (font->GetTextWidth((byte *)m_Text + m_ScrollOffset, std::max(0, m_SelStart - m_ScrollOffset)) +
+ sfont->GetTextWidth((byte *)(m_Text + std::max(m_ScrollOffset, m_SelStart)), m_SelEnd - std::max(m_ScrollOffset, m_SelStart))
+
+ > m_Width - CursorWidth - 2 * m_FrameWidth) {
+ m_ScrollOffset++;
+ if (m_ScrollOffset >= strlen(m_Text)) break;
+ }
+
+ m_ScrollOffset = std::min(m_ScrollOffset, m_SelEnd);
+
+ s1 = m_SelStart;
+ s2 = m_SelEnd;
+ CurFirst = false;
+ }
+
+
+ int AlignOffset = 0;
+
+ for (int Count = 0; Count < 2; Count++) {
+ // draw text
+ int xxx, yyy, width, height;
+
+ xxx = m_PosX + m_FrameWidth + OffsetX;
+ yyy = m_PosY + m_FrameWidth + OffsetY;
+
+ width = m_PosX + m_Width + OffsetX - m_FrameWidth;
+ height = std::max(font->GetLetterHeight(), sfont->GetLetterHeight());
+
+ if (Game->m_TextRTL) xxx += AlignOffset;
+
+ TTextAlign Align = TAL_LEFT;
+
+
+ // unselected 1
+ if (s1 > m_ScrollOffset) {
+ if (Count) font->DrawText((byte *)m_Text + m_ScrollOffset, xxx, yyy, width - xxx, Align, height, s1 - m_ScrollOffset);
+ xxx += font->GetTextWidth((byte *)m_Text + m_ScrollOffset, s1 - m_ScrollOffset);
+ AlignOffset += font->GetTextWidth((byte *)m_Text + m_ScrollOffset, s1 - m_ScrollOffset);
+ }
+
+ // cursor
+ if (focused && CurFirst) {
+ if (Count) {
+ if (CBPlatform::GetTime() - m_LastBlinkTime >= m_CursorBlinkRate) {
+ m_LastBlinkTime = CBPlatform::GetTime();
+ m_CursorVisible = !m_CursorVisible;
+ }
+ if (m_CursorVisible)
+ font->DrawText((byte *)m_CursorChar, xxx, yyy, width - xxx, Align, height, 1);
+ }
+ xxx += CursorWidth;
+ AlignOffset += CursorWidth;
+ }
+
+ // selected
+ int s3 = std::max(s1, m_ScrollOffset);
+
+ if (s2 - s3 > 0) {
+ if (Count) sfont->DrawText((byte *)m_Text + s3, xxx, yyy, width - xxx, Align, height, s2 - s3);
+ xxx += sfont->GetTextWidth((byte *)m_Text + s3, s2 - s3);
+ AlignOffset += sfont->GetTextWidth((byte *)m_Text + s3, s2 - s3);
+ }
+
+ // cursor
+ if (focused && !CurFirst) {
+ if (Count) {
+ if (CBPlatform::GetTime() - m_LastBlinkTime >= m_CursorBlinkRate) {
+ m_LastBlinkTime = CBPlatform::GetTime();
+ m_CursorVisible = !m_CursorVisible;
+ }
+ if (m_CursorVisible)
+ font->DrawText((byte *)m_CursorChar, xxx, yyy, width - xxx, Align, height, 1);
+ }
+ xxx += CursorWidth;
+ AlignOffset += CursorWidth;
+ }
+
+ // unselected 2
+ if (Count) font->DrawText((byte *)m_Text + s2, xxx, yyy, width - xxx, Align, height);
+ AlignOffset += font->GetTextWidth((byte *)m_Text + s2);
+
+ AlignOffset = (m_Width - 2 * m_FrameWidth) - AlignOffset;
+ if (AlignOffset < 0) AlignOffset = 0;
+ }
+
+
+ Game->m_Renderer->m_RectList.Add(new CBActiveRect(Game, this, NULL, OffsetX + m_PosX, OffsetY + m_PosY, m_Width, m_Height, 100, 100, false));
+
+
+ Game->m_TextEncoding = OrigEncoding;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIEdit::HandleKeypress(SDL_Event *event) {
+ bool Handled = false;
+
+ if (event->type == SDL_KEYDOWN) {
+ switch (event->key.keysym.sym) {
+ case SDLK_ESCAPE:
+ case SDLK_TAB:
+ case SDLK_RETURN:
+ return false;
+
+ // ctrl+A
+ case SDLK_a:
+ if (CBKeyboardState::IsControlDown()) {
+ m_SelStart = 0;
+ m_SelEnd = strlen(m_Text);
+ Handled = true;
+ }
+ break;
+
+ case SDLK_BACKSPACE:
+ if (m_SelStart == m_SelEnd) {
+ if (Game->m_TextRTL) DeleteChars(m_SelStart, m_SelStart + 1);
+ else DeleteChars(m_SelStart - 1, m_SelStart);
+ } else DeleteChars(m_SelStart, m_SelEnd);
+ if (m_SelEnd >= m_SelStart) m_SelEnd -= std::max(1, m_SelEnd - m_SelStart);
+ m_SelStart = m_SelEnd;
+
+ Handled = true;
+ break;
+
+ case SDLK_LEFT:
+ case SDLK_UP:
+ m_SelEnd--;
+ if (!CBKeyboardState::IsShiftDown()) m_SelStart = m_SelEnd;
+ Handled = true;
+ break;
+
+ case SDLK_RIGHT:
+ case SDLK_DOWN:
+ m_SelEnd++;
+ if (!CBKeyboardState::IsShiftDown()) m_SelStart = m_SelEnd;
+ Handled = true;
+ break;
+
+ case SDLK_HOME:
+ if (Game->m_TextRTL) {
+ m_SelEnd = strlen(m_Text);
+ if (!CBKeyboardState::IsShiftDown()) m_SelStart = m_SelEnd;
+ } else {
+ m_SelEnd = 0;
+ if (!CBKeyboardState::IsShiftDown()) m_SelStart = m_SelEnd;
+ }
+ Handled = true;
+ break;
+
+ case SDLK_END:
+ if (Game->m_TextRTL) {
+ m_SelEnd = 0;
+ if (!CBKeyboardState::IsShiftDown()) m_SelStart = m_SelEnd;
+ } else {
+ m_SelEnd = strlen(m_Text);
+ if (!CBKeyboardState::IsShiftDown()) m_SelStart = m_SelEnd;
+ }
+ Handled = true;
+ break;
+
+ case SDLK_DELETE:
+ if (m_SelStart == m_SelEnd) {
+ if (Game->m_TextRTL) {
+ DeleteChars(m_SelStart - 1, m_SelStart);
+ m_SelEnd--;
+ if (m_SelEnd < 0) m_SelEnd = 0;
+ } else DeleteChars(m_SelStart, m_SelStart + 1);
+ } else DeleteChars(m_SelStart, m_SelEnd);
+ if (m_SelEnd > m_SelStart) m_SelEnd -= (m_SelEnd - m_SelStart);
+
+ m_SelStart = m_SelEnd;
+ Handled = true;
+ break;
+ }
+ return Handled;
+ }
+
+ else if (event->type == SDL_TEXTINPUT) {
+ if (m_SelStart != m_SelEnd) DeleteChars(m_SelStart, m_SelEnd);
+
+ WideString wstr = StringUtil::Utf8ToWide(event->text.text);
+ m_SelEnd += InsertChars(m_SelEnd, (byte *)StringUtil::WideToAnsi(wstr).c_str(), 1);
+
+ if (Game->m_TextRTL) m_SelEnd = m_SelStart;
+ else m_SelStart = m_SelEnd;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+int CUIEdit::DeleteChars(int Start, int End) {
+ if (Start > End) CBUtils::Swap(&Start, &End);
+
+ Start = MAX(Start, 0);
+ End = MIN(End, strlen(m_Text));
+
+ char *str = new char[strlen(m_Text) - (End - Start) + 1];
+ if (str) {
+ if (Start > 0) memcpy(str, m_Text, Start);
+ memcpy(str + std::max(0, Start), m_Text + End, strlen(m_Text) - End + 1);
+
+ delete[] m_Text;
+ m_Text = str;
+ }
+ if (m_ParentNotify && m_Parent) m_Parent->ApplyEvent(m_Name);
+
+ return End - Start;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int CUIEdit::InsertChars(int Pos, byte *Chars, int Num) {
+ if (strlen(m_Text) + Num > m_MaxLength) {
+ Num -= (strlen(m_Text) + Num - m_MaxLength);
+ }
+
+ Pos = MAX(Pos, 0);
+ Pos = MIN(Pos, strlen(m_Text));
+
+ char *str = new char[strlen(m_Text) + Num + 1];
+ if (str) {
+ if (Pos > 0) memcpy(str, m_Text, Pos);
+ memcpy(str + Pos + Num, m_Text + Pos, strlen(m_Text) - Pos + 1);
+
+ memcpy(str + Pos, Chars, Num);
+
+ delete[] m_Text;
+ m_Text = str;
+ }
+ if (m_ParentNotify && m_Parent) m_Parent->ApplyEvent(m_Name);
+
+ return Num;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(m_CursorBlinkRate));
+ PersistMgr->Transfer(TMEMBER(m_CursorChar));
+ PersistMgr->Transfer(TMEMBER(m_FontSelected));
+ PersistMgr->Transfer(TMEMBER(m_FrameWidth));
+ PersistMgr->Transfer(TMEMBER(m_MaxLength));
+ PersistMgr->Transfer(TMEMBER(m_ScrollOffset));
+ PersistMgr->Transfer(TMEMBER(m_SelEnd));
+ PersistMgr->Transfer(TMEMBER(m_SelStart));
+
+ if (!PersistMgr->m_Saving) {
+ m_CursorVisible = false;
+ m_LastBlinkTime = 0;
+ }
+
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UIEdit.h b/engines/wintermute/UIEdit.h
new file mode 100644
index 0000000000..134218c877
--- /dev/null
+++ b/engines/wintermute/UIEdit.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIEDIT_H
+#define WINTERMUTE_UIEDIT_H
+
+#include "persistent.h"
+#include "UIObject.h"
+
+namespace WinterMute {
+class CBFont;
+class CUIEdit : public CUIObject {
+public:
+ DECLARE_PERSISTENT(CUIEdit, CUIObject)
+ int m_MaxLength;
+ int InsertChars(int Pos, byte *Chars, int Num);
+ int DeleteChars(int Start, int End);
+ bool m_CursorVisible;
+ uint32 m_LastBlinkTime;
+ virtual HRESULT Display(int OffsetX, int OffsetY);
+ virtual bool HandleKeypress(SDL_Event *event);
+ int m_ScrollOffset;
+ int m_FrameWidth;
+ uint32 m_CursorBlinkRate;
+ void SetCursorChar(char *Char);
+ char *m_CursorChar;
+ int m_SelEnd;
+ int m_SelStart;
+ CBFont *m_FontSelected;
+ CUIEdit(CBGame *inGame);
+ virtual ~CUIEdit();
+
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UIEntity.cpp b/engines/wintermute/UIEntity.cpp
new file mode 100644
index 0000000000..2cf7a3096f
--- /dev/null
+++ b/engines/wintermute/UIEntity.cpp
@@ -0,0 +1,339 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/AdEntity.h"
+#include "engines/wintermute/BGame.h"
+#include "engines/wintermute/BFileManager.h"
+#include "engines/wintermute/UIEntity.h"
+#include "engines/wintermute/BParser.h"
+#include "engines/wintermute/BDynBuffer.h"
+#include "engines/wintermute/scriptables/ScValue.h"
+#include "engines/wintermute/scriptables/ScScript.h"
+#include "engines/wintermute/scriptables/ScStack.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIEntity, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIEntity::CUIEntity(CBGame *inGame): CUIObject(inGame) {
+ m_Type = UI_CUSTOM;
+ m_Entity = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIEntity::~CUIEntity() {
+ if (m_Entity) Game->UnregisterObject(m_Entity);
+ m_Entity = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::LoadFile(char *Filename) {
+ byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIEntity::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ m_Filename = new char [strlen(Filename) + 1];
+ strcpy(m_Filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing ENTITY container file '%s'", Filename);
+
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(ENTITY_CONTAINER)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(NAME)
+TOKEN_DEF(ENTITY)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(ENTITY_CONTAINER)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(ENTITY)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_ENTITY_CONTAINER) {
+ Game->LOG(0, "'ENTITY_CONTAINER' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &m_PosX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &m_PosY);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &m_Disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &m_Visible);
+ break;
+
+ case TOKEN_ENTITY:
+ if (FAILED(SetEntity((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in ENTITY_CONTAINER definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading ENTITY_CONTAINER definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ if (Game->m_EditorMode) {
+ m_Width = 50;
+ m_Height = 50;
+ }
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "ENTITY_CONTAINER\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", m_PosX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", m_PosY);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", m_Disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", m_Visible ? "TRUE" : "FALSE");
+
+ if (m_Entity && m_Entity->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "ENTITY=\"%s\"\n", m_Entity->m_Filename);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < m_Scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::SetEntity(char *Filename) {
+ if (m_Entity) Game->UnregisterObject(m_Entity);
+ m_Entity = new CAdEntity(Game);
+ if (!m_Entity || FAILED(m_Entity->LoadFile(Filename))) {
+ delete m_Entity;
+ m_Entity = NULL;
+ return E_FAIL;
+ } else {
+ m_Entity->m_NonIntMouseEvents = true;
+ m_Entity->m_SceneIndependent = true;
+ m_Entity->MakeFreezable(false);
+ Game->RegisterObject(m_Entity);
+ }
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::Display(int OffsetX, int OffsetY) {
+ if (!m_Visible) return S_OK;
+
+ if (m_Entity) {
+ m_Entity->m_PosX = OffsetX + m_PosX;
+ m_Entity->m_PosY = OffsetY + m_PosY;
+ if (m_Entity->m_Scale < 0) m_Entity->m_Zoomable = false;
+ m_Entity->m_Shadowable = false;
+
+ m_Entity->Update();
+
+ bool OrigReg = m_Entity->m_Registrable;
+
+ if (m_Entity->m_Registrable && m_Disable) m_Entity->m_Registrable = false;
+
+ m_Entity->Display();
+ m_Entity->m_Registrable = OrigReg;
+ }
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // GetEntity
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "GetEntity") == 0) {
+ Stack->CorrectParams(0);
+
+ if (m_Entity) Stack->PushNative(m_Entity, true);
+ else Stack->PushNULL();
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetEntity
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetEntity") == 0) {
+ Stack->CorrectParams(1);
+
+ char *Filename = Stack->Pop()->GetString();
+
+ if (SUCCEEDED(SetEntity(Filename)))
+ Stack->PushBool(true);
+ else
+ Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIEntity::ScGetProperty(char *Name) {
+ m_ScValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ m_ScValue->SetString("entity container");
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Freezable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Freezable") == 0) {
+ if (m_Entity) m_ScValue->SetBool(m_Entity->m_Freezable);
+ else m_ScValue->SetBool(false);
+ return m_ScValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::ScSetProperty(char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Freezable
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Freezable") == 0) {
+ if (m_Entity) m_Entity->MakeFreezable(Value->GetBool());
+ return S_OK;
+ } else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CUIEntity::ScToString() {
+ return "[entity container]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(m_Entity));
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UIEntity.h b/engines/wintermute/UIEntity.h
new file mode 100644
index 0000000000..f3c9385b7b
--- /dev/null
+++ b/engines/wintermute/UIEntity.h
@@ -0,0 +1,58 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIENTITY_H
+#define WINTERMUTE_UIENTITY_H
+
+#include "UIObject.h"
+
+namespace WinterMute {
+class CAdEntity;
+class CUIEntity : public CUIObject {
+public:
+ DECLARE_PERSISTENT(CUIEntity, CUIObject)
+ CUIEntity(CBGame *inGame);
+ virtual ~CUIEntity();
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ CAdEntity *m_Entity;
+ HRESULT SetEntity(char *Filename);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UIObject.cpp b/engines/wintermute/UIObject.cpp
new file mode 100644
index 0000000000..4ff0952bd7
--- /dev/null
+++ b/engines/wintermute/UIObject.cpp
@@ -0,0 +1,589 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/BGame.h"
+#include "engines/wintermute/BSprite.h"
+#include "engines/wintermute/UIObject.h"
+#include "engines/wintermute/UITiledImage.h"
+#include "engines/wintermute/UIWindow.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/scriptables/ScValue.h"
+#include "engines/wintermute/scriptables/ScStack.h"
+#include "engines/wintermute/BFontStorage.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIObject, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIObject::CUIObject(CBGame *inGame): CBObject(inGame) {
+ m_Back = NULL;
+ m_Image = NULL;
+ m_Font = NULL;
+ m_Text = NULL;
+ m_SharedFonts = m_SharedImages = false;
+
+ m_Width = m_Height = 0;
+
+ m_ListenerObject = NULL;
+ m_ListenerParamObject = NULL;
+ m_ListenerParamDWORD = 0;
+
+ m_Disable = false;
+ m_Visible = true;
+
+ m_Type = UI_UNKNOWN;
+ m_Parent = NULL;
+
+ m_ParentNotify = false;
+
+ m_FocusedWidget = NULL;
+
+ m_CanFocus = false;
+ m_NonIntMouseEvents = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIObject::~CUIObject() {
+ if (!Game->m_LoadInProgress) CSysClassRegistry::GetInstance()->EnumInstances(CBGame::InvalidateValues, "CScValue", (void *)this);
+
+ if (m_Back) delete m_Back;
+ if (m_Font && !m_SharedFonts) Game->m_FontStorage->RemoveFont(m_Font);
+
+ if (m_Image && !m_SharedImages) delete m_Image;
+
+ if (m_Text) delete [] m_Text;
+
+ m_FocusedWidget = NULL; // ref only
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIObject::SetText(const char *Text) {
+ if (m_Text) delete [] m_Text;
+ m_Text = new char [strlen(Text) + 1];
+ if (m_Text) {
+ strcpy(m_Text, Text);
+ for (int i = 0; i < strlen(m_Text); i++) {
+ if (m_Text[i] == '|') m_Text[i] = '\n';
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::Display(int OffsetX, int OffsetY) {
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIObject::SetListener(CBScriptHolder *Object, CBScriptHolder *ListenerObject, uint32 ListenerParam) {
+ m_ListenerObject = Object;
+ m_ListenerParamObject = ListenerObject;
+ m_ListenerParamDWORD = ListenerParam;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIObject::CorrectSize() {
+ RECT rect;
+
+ if (m_Width <= 0) {
+ if (m_Image) {
+ m_Image->GetBoundingRect(&rect, 0, 0);
+ m_Width = rect.right - rect.left;
+ } else m_Width = 100;
+ }
+
+ if (m_Height <= 0) {
+ if (m_Image) {
+ m_Image->GetBoundingRect(&rect, 0, 0);
+ m_Height = rect.bottom - rect.top;
+ }
+ }
+
+ if (m_Back) m_Back->CorrectSize(&m_Width, &m_Height);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetFont
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SetFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
+ if (Val->IsNULL()) {
+ m_Font = NULL;
+ Stack->PushBool(true);
+ } else {
+ m_Font = Game->m_FontStorage->AddFont(Val->GetString());
+ Stack->PushBool(m_Font != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetImage") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ char *Filename = Val->GetString();
+
+ delete m_Image;
+ m_Image = NULL;
+ if (Val->IsNULL()) {
+ Stack->PushBool(true);
+ return S_OK;
+ }
+
+ m_Image = new CBSprite(Game);
+ if (!m_Image || FAILED(m_Image->LoadFile(Val->GetString()))) {
+ delete m_Image;
+ m_Image = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_Image || !m_Image->m_Filename) Stack->PushNULL();
+ else Stack->PushString(m_Image->m_Filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_Image) Stack->PushNULL();
+ else Stack->PushNative(m_Image, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Focus
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Focus") == 0) {
+ Stack->CorrectParams(0);
+ Focus();
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveAfter / MoveBefore
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MoveAfter") == 0 || strcmp(Name, "MoveBefore") == 0) {
+ Stack->CorrectParams(1);
+
+ if (m_Parent && m_Parent->m_Type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)m_Parent;
+
+ int i;
+ bool found = false;
+ CScValue *val = Stack->Pop();
+ // find directly
+ if (val->IsNative()) {
+ CUIObject *widget = (CUIObject *)val->GetNative();
+ for (i = 0; i < win->m_Widgets.GetSize(); i++) {
+ if (win->m_Widgets[i] == widget) {
+ found = true;
+ break;
+ }
+ }
+ }
+ // find by name
+ else {
+ char *name = val->GetString();
+ for (i = 0; i < win->m_Widgets.GetSize(); i++) {
+ if (scumm_stricmp(win->m_Widgets[i]->m_Name, name) == 0) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ bool done = false;
+ for (int j = 0; j < win->m_Widgets.GetSize(); j++) {
+ if (win->m_Widgets[j] == this) {
+ if (strcmp(Name, "MoveAfter") == 0) i++;
+ if (j >= i) j++;
+
+ win->m_Widgets.InsertAt(i, this);
+ win->m_Widgets.RemoveAt(j);
+
+ done = true;
+ Stack->PushBool(true);
+ break;
+ }
+ }
+ if (!done) Stack->PushBool(false);
+ } else Stack->PushBool(false);
+
+ } else Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveToBottom
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MoveToBottom") == 0) {
+ Stack->CorrectParams(0);
+
+ if (m_Parent && m_Parent->m_Type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)m_Parent;
+ for (int i = 0; i < win->m_Widgets.GetSize(); i++) {
+ if (win->m_Widgets[i] == this) {
+ win->m_Widgets.RemoveAt(i);
+ win->m_Widgets.InsertAt(0, this);
+ break;
+ }
+ }
+ Stack->PushBool(true);
+ } else Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveToTop
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MoveToTop") == 0) {
+ Stack->CorrectParams(0);
+
+ if (m_Parent && m_Parent->m_Type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)m_Parent;
+ for (int i = 0; i < win->m_Widgets.GetSize(); i++) {
+ if (win->m_Widgets[i] == this) {
+ win->m_Widgets.RemoveAt(i);
+ win->m_Widgets.Add(this);
+ break;
+ }
+ }
+ Stack->PushBool(true);
+ } else Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ else return CBObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIObject::ScGetProperty(char *Name) {
+ m_ScValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ m_ScValue->SetString("ui_object");
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Name") == 0) {
+ m_ScValue->SetString(m_Name);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Parent (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Parent") == 0) {
+ m_ScValue->SetNative(m_Parent, true);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ParentNotify
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ParentNotify") == 0) {
+ m_ScValue->SetBool(m_ParentNotify);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Width") == 0) {
+ m_ScValue->SetInt(m_Width);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Height") == 0) {
+ m_ScValue->SetInt(m_Height);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Visible
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Visible") == 0) {
+ m_ScValue->SetBool(m_Visible);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Disabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Disabled") == 0) {
+ m_ScValue->SetBool(m_Disable);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ m_ScValue->SetString(m_Text);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NextSibling (RO) / PrevSibling (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "NextSibling") == 0 || strcmp(Name, "PrevSibling") == 0) {
+ m_ScValue->SetNULL();
+ if (m_Parent && m_Parent->m_Type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)m_Parent;
+ for (int i = 0; i < win->m_Widgets.GetSize(); i++) {
+ if (win->m_Widgets[i] == this) {
+ if (strcmp(Name, "NextSibling") == 0) {
+ if (i < win->m_Widgets.GetSize() - 1) m_ScValue->SetNative(win->m_Widgets[i + 1], true);
+ } else {
+ if (i > 0) m_ScValue->SetNative(win->m_Widgets[i - 1], true);
+ }
+ break;
+ }
+ }
+ }
+ return m_ScValue;
+ }
+
+ else return CBObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::ScSetProperty(char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Name") == 0) {
+ SetName(Value->GetString());
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ParentNotify
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ParentNotify") == 0) {
+ m_ParentNotify = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Width") == 0) {
+ m_Width = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Height") == 0) {
+ m_Height = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Visible
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Visible") == 0) {
+ m_Visible = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Disabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Disabled") == 0) {
+ m_Disable = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ SetText(Value->GetString());
+ return S_OK;
+ }
+
+ else return CBObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CUIObject::ScToString() {
+ return "[ui_object]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIObject::IsFocused() {
+ if (!Game->m_FocusedWindow) return false;
+ if (Game->m_FocusedWindow == this) return true;
+
+ CUIObject *obj = Game->m_FocusedWindow;
+ while (obj) {
+ if (obj == this) return true;
+ else obj = obj->m_FocusedWidget;
+ }
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::HandleMouse(TMouseEvent Event, TMouseButton Button) {
+ // handle focus change
+ if (Event == MOUSE_CLICK && Button == MOUSE_BUTTON_LEFT) {
+ Focus();
+ }
+ return CBObject::HandleMouse(Event, Button);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::Focus() {
+ CUIObject *obj = this;
+ bool disabled = false;
+ while (obj) {
+ if (obj->m_Disable && obj->m_Type == UI_WINDOW) {
+ disabled = true;
+ break;
+ }
+ obj = obj->m_Parent;
+ }
+ if (!disabled) {
+ obj = this;
+ while (obj) {
+ if (obj->m_Parent) {
+ if (!obj->m_Disable && obj->m_CanFocus) obj->m_Parent->m_FocusedWidget = obj;
+ } else {
+ if (obj->m_Type == UI_WINDOW) Game->FocusWindow((CUIWindow *)obj);
+ }
+
+ obj = obj->m_Parent;
+ }
+ }
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::GetTotalOffset(int *OffsetX, int *OffsetY) {
+ int OffX = 0, OffY = 0;
+
+ CUIObject *obj = m_Parent;
+ while (obj) {
+ OffX += obj->m_PosX;
+ OffY += obj->m_PosY;
+
+ obj = obj->m_Parent;
+ }
+ if (OffsetX) *OffsetX = OffX;
+ if (OffsetY) *OffsetY = OffY;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::Persist(CBPersistMgr *PersistMgr) {
+
+ CBObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(m_Back));
+ PersistMgr->Transfer(TMEMBER(m_CanFocus));
+ PersistMgr->Transfer(TMEMBER(m_Disable));
+ PersistMgr->Transfer(TMEMBER(m_FocusedWidget));
+ PersistMgr->Transfer(TMEMBER(m_Font));
+ PersistMgr->Transfer(TMEMBER(m_Height));
+ PersistMgr->Transfer(TMEMBER(m_Image));
+ PersistMgr->Transfer(TMEMBER(m_ListenerObject));
+ PersistMgr->Transfer(TMEMBER(m_ListenerParamObject));
+ PersistMgr->Transfer(TMEMBER(m_ListenerParamDWORD));
+ PersistMgr->Transfer(TMEMBER(m_Parent));
+ PersistMgr->Transfer(TMEMBER(m_ParentNotify));
+ PersistMgr->Transfer(TMEMBER(m_SharedFonts));
+ PersistMgr->Transfer(TMEMBER(m_SharedImages));
+ PersistMgr->Transfer(TMEMBER(m_Text));
+ PersistMgr->Transfer(TMEMBER_INT(m_Type));
+ PersistMgr->Transfer(TMEMBER(m_Visible));
+ PersistMgr->Transfer(TMEMBER(m_Width));
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ return E_FAIL;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UIObject.h b/engines/wintermute/UIObject.h
new file mode 100644
index 0000000000..9742307504
--- /dev/null
+++ b/engines/wintermute/UIObject.h
@@ -0,0 +1,83 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIOBJECT_H
+#define WINTERMUTE_UIOBJECT_H
+
+
+#include "BObject.h"
+#include "dctypes.h" // Added by ClassView
+
+namespace WinterMute {
+
+class CUITiledImage;
+class CBFont;
+class CUIObject : public CBObject {
+public:
+
+ HRESULT GetTotalOffset(int *OffsetX, int *OffsetY);
+ bool m_CanFocus;
+ HRESULT Focus();
+ virtual HRESULT HandleMouse(TMouseEvent Event, TMouseButton Button);
+ bool IsFocused();
+ bool m_ParentNotify;
+ DECLARE_PERSISTENT(CUIObject, CBObject)
+ CUIObject *m_Parent;
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ virtual void CorrectSize();
+ bool m_SharedFonts;
+ bool m_SharedImages;
+ void SetText(const char *Text);
+ char *m_Text;
+ CBFont *m_Font;
+ bool m_Visible;
+ CUITiledImage *m_Back;
+ bool m_Disable;
+ CUIObject(CBGame *inGame = NULL);
+ virtual ~CUIObject();
+ int m_Width;
+ int m_Height;
+ TUIObjectType m_Type;
+ CBSprite *m_Image;
+ void SetListener(CBScriptHolder *Object, CBScriptHolder *ListenerObject, uint32 ListenerParam);
+ CBScriptHolder *m_ListenerParamObject;
+ uint32 m_ListenerParamDWORD;
+ CBScriptHolder *m_ListenerObject;
+ CUIObject *m_FocusedWidget;
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UIText.cpp b/engines/wintermute/UIText.cpp
new file mode 100644
index 0000000000..7a0b206cec
--- /dev/null
+++ b/engines/wintermute/UIText.cpp
@@ -0,0 +1,484 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "dcgf.h"
+#include "BDynBuffer.h"
+#include "UIText.h"
+#include "UITiledImage.h"
+#include "BGame.h"
+#include "BParser.h"
+#include "ScValue.h"
+#include "BFont.h"
+#include "BFontStorage.h"
+#include "BStringTable.h"
+#include "ScScript.h"
+#include "ScStack.h"
+#include "BSprite.h"
+#include "BFileManager.h"
+#include "PlatformSDL.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIText, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIText::CUIText(CBGame *inGame): CUIObject(inGame) {
+ m_TextAlign = TAL_LEFT;
+ m_VerticalAlign = VAL_CENTER;
+ m_Type = UI_STATIC;
+ m_CanFocus = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIText::~CUIText() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::Display(int OffsetX, int OffsetY) {
+ if (!m_Visible) return S_OK;
+
+
+ CBFont *font = m_Font;
+ if (!font) font = Game->m_SystemFont;
+
+ if (m_Back) m_Back->Display(OffsetX + m_PosX, OffsetY + m_PosY, m_Width, m_Height);
+ if (m_Image) m_Image->Draw(OffsetX + m_PosX, OffsetY + m_PosY, NULL);
+
+ if (font && m_Text) {
+ int text_offset;
+ switch (m_VerticalAlign) {
+ case VAL_TOP:
+ text_offset = 0;
+ break;
+ case VAL_BOTTOM:
+ text_offset = m_Height - font->GetTextHeight((byte *)m_Text, m_Width);
+ break;
+ default:
+ text_offset = (m_Height - font->GetTextHeight((byte *)m_Text, m_Width)) / 2;
+ }
+ font->DrawText((byte *)m_Text, OffsetX + m_PosX, OffsetY + m_PosY + text_offset, m_Width, m_TextAlign, m_Height);
+ }
+
+ //Game->m_Renderer->m_RectList.Add(new CBActiveRect(Game, this, NULL, OffsetX + m_PosX, OffsetY + m_PosY, m_Width, m_Height, 100, 100, false));
+
+ return S_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::LoadFile(char *Filename) {
+ byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIText::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ m_Filename = new char [strlen(Filename) + 1];
+ strcpy(m_Filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing STATIC file '%s'", Filename);
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(STATIC)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(BACK)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TEXT_ALIGN)
+TOKEN_DEF(VERTICAL_ALIGN)
+TOKEN_DEF(TEXT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(NAME)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(STATIC)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TEXT_ALIGN)
+ TOKEN_TABLE(VERTICAL_ALIGN)
+ TOKEN_TABLE(TEXT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_STATIC) {
+ Game->LOG(0, "'STATIC' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete m_Back;
+ m_Back = new CUITiledImage(Game);
+ if (!m_Back || FAILED(m_Back->LoadFile((char *)params))) {
+ delete m_Back;
+ m_Back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete m_Image;
+ m_Image = new CBSprite(Game);
+ if (!m_Image || FAILED(m_Image->LoadFile((char *)params))) {
+ delete m_Image;
+ m_Image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
+ m_Font = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_Font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TEXT:
+ SetText((char *)params);
+ Game->m_StringTable->Expand(&m_Text);
+ break;
+
+ case TOKEN_TEXT_ALIGN:
+ if (scumm_stricmp((char *)params, "left") == 0) m_TextAlign = TAL_LEFT;
+ else if (scumm_stricmp((char *)params, "right") == 0) m_TextAlign = TAL_RIGHT;
+ else m_TextAlign = TAL_CENTER;
+ break;
+
+ case TOKEN_VERTICAL_ALIGN:
+ if (scumm_stricmp((char *)params, "top") == 0) m_VerticalAlign = VAL_TOP;
+ else if (scumm_stricmp((char *)params, "bottom") == 0) m_VerticalAlign = VAL_BOTTOM;
+ else m_VerticalAlign = VAL_CENTER;
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &m_PosX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &m_PosY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &m_Width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &m_Height);
+ break;
+
+ case TOKEN_CURSOR:
+ delete m_Cursor;
+ m_Cursor = new CBSprite(Game);
+ if (!m_Cursor || FAILED(m_Cursor->LoadFile((char *)params))) {
+ delete m_Cursor;
+ m_Cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &m_ParentNotify);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &m_Disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &m_Visible);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in STATIC definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading STATIC definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "STATIC\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Back && m_Back->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", m_Back->m_Filename);
+
+ if (m_Image && m_Image->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", m_Image->m_Filename);
+
+ if (m_Font && m_Font->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", m_Font->m_Filename);
+
+ if (m_Cursor && m_Cursor->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", m_Cursor->m_Filename);
+
+ if (m_Text)
+ Buffer->PutTextIndent(Indent + 2, "TEXT=\"%s\"\n", m_Text);
+
+ switch (m_TextAlign) {
+ case TAL_LEFT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "left");
+ break;
+ case TAL_RIGHT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "right");
+ break;
+ case TAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "center");
+ break;
+ }
+
+ switch (m_VerticalAlign) {
+ case VAL_TOP:
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "top");
+ break;
+ case VAL_BOTTOM:
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "bottom");
+ break;
+ case VAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "center");
+ break;
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", m_PosX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", m_PosY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", m_Width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", m_Height);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", m_Disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", m_Visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", m_ParentNotify ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < m_Scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SizeToFit
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SizeToFit") == 0) {
+ Stack->CorrectParams(0);
+ SizeToFit();
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HeightToFit
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "HeightToFit") == 0) {
+ Stack->CorrectParams(0);
+ if (m_Font && m_Text) m_Height = m_Font->GetTextHeight((byte *)m_Text, m_Width);
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIText::ScGetProperty(char *Name) {
+ m_ScValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ m_ScValue->SetString("static");
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "TextAlign") == 0) {
+ m_ScValue->SetInt(m_TextAlign);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // VerticalAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "VerticalAlign") == 0) {
+ m_ScValue->SetInt(m_VerticalAlign);
+ return m_ScValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::ScSetProperty(char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "TextAlign") == 0) {
+ int i = Value->GetInt();
+ if (i < 0 || i >= NUM_TEXT_ALIGN) i = 0;
+ m_TextAlign = (TTextAlign)i;
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // VerticalAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "VerticalAlign") == 0) {
+ int i = Value->GetInt();
+ if (i < 0 || i >= NUM_VERTICAL_ALIGN) i = 0;
+ m_VerticalAlign = (TVerticalAlign)i;
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CUIText::ScToString() {
+ return "[static]";
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+ PersistMgr->Transfer(TMEMBER_INT(m_TextAlign));
+ PersistMgr->Transfer(TMEMBER_INT(m_VerticalAlign));
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::SizeToFit() {
+ if (m_Font && m_Text) {
+ m_Width = m_Font->GetTextWidth((byte *)m_Text);
+ m_Height = m_Font->GetTextHeight((byte *)m_Text, m_Width);
+ }
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UIText.h b/engines/wintermute/UIText.h
new file mode 100644
index 0000000000..74158cb636
--- /dev/null
+++ b/engines/wintermute/UIText.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UITEXT_H
+#define WINTERMUTE_UITEXT_H
+
+
+#include "UIObject.h"
+
+namespace WinterMute {
+
+class CUIText : public CUIObject {
+public:
+ HRESULT SizeToFit();
+ virtual HRESULT Display(int OffsetX, int OffsetY);
+ DECLARE_PERSISTENT(CUIText, CUIObject)
+ CUIText(CBGame *inGame = NULL);
+ virtual ~CUIText();
+ TTextAlign m_TextAlign;
+ TVerticalAlign m_VerticalAlign;
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UITiledImage.cpp b/engines/wintermute/UITiledImage.cpp
new file mode 100644
index 0000000000..488c1bdd7b
--- /dev/null
+++ b/engines/wintermute/UITiledImage.cpp
@@ -0,0 +1,368 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/UITiledImage.h"
+#include "engines/wintermute/BSurface.h"
+#include "engines/wintermute/BDynBuffer.h"
+#include "engines/wintermute/BParser.h"
+#include "engines/wintermute/BGame.h"
+#include "engines/wintermute/BSubFrame.h"
+#include "engines/wintermute/BFileManager.h"
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUITiledImage, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUITiledImage::CUITiledImage(CBGame *inGame): CBObject(inGame) {
+ m_Image = NULL;
+
+ CBPlatform::SetRectEmpty(&m_UpLeft);
+ CBPlatform::SetRectEmpty(&m_UpMiddle);
+ CBPlatform::SetRectEmpty(&m_UpRight);
+ CBPlatform::SetRectEmpty(&m_MiddleLeft);
+ CBPlatform::SetRectEmpty(&m_MiddleMiddle);
+ CBPlatform::SetRectEmpty(&m_MiddleRight);
+ CBPlatform::SetRectEmpty(&m_DownLeft);
+ CBPlatform::SetRectEmpty(&m_DownMiddle);
+ CBPlatform::SetRectEmpty(&m_DownRight);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUITiledImage::~CUITiledImage() {
+ SAFE_DELETE(m_Image);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::Display(int X, int Y, int Width, int Height) {
+ if (!m_Image) return E_FAIL;
+
+ int tile_width = m_MiddleMiddle.right - m_MiddleMiddle.left;
+ int tile_height = m_MiddleMiddle.bottom - m_MiddleMiddle.top;
+
+ int num_columns = (Width - (m_MiddleLeft.right - m_MiddleLeft.left) - (m_MiddleRight.right - m_MiddleRight.left)) / tile_width;
+ int num_rows = (Height - (m_UpMiddle.bottom - m_UpMiddle.top) - (m_DownMiddle.bottom - m_DownMiddle.top)) / tile_height;
+
+ int col, row;
+
+ Game->m_Renderer->StartSpriteBatch();
+
+ // top left/right
+ m_Image->m_Surface->DisplayTrans(X, Y, m_UpLeft);
+ m_Image->m_Surface->DisplayTrans(X + (m_UpLeft.right - m_UpLeft.left) + num_columns * tile_width, Y, m_UpRight);
+
+ // bottom left/right
+ m_Image->m_Surface->DisplayTrans(X, Y + (m_UpMiddle.bottom - m_UpMiddle.top) + num_rows * tile_height, m_DownLeft);
+ m_Image->m_Surface->DisplayTrans(X + (m_UpLeft.right - m_UpLeft.left) + num_columns * tile_width, Y + (m_UpMiddle.bottom - m_UpMiddle.top) + num_rows * tile_height, m_DownRight);
+
+ // left/right
+ int yyy = Y + (m_UpMiddle.bottom - m_UpMiddle.top);
+ for (row = 0; row < num_rows; row++) {
+ m_Image->m_Surface->DisplayTrans(X, yyy, m_MiddleLeft);
+ m_Image->m_Surface->DisplayTrans(X + (m_MiddleLeft.right - m_MiddleLeft.left) + num_columns * tile_width, yyy, m_MiddleRight);
+ yyy += tile_width;
+ }
+
+ // top/bottom
+ int xxx = X + (m_UpLeft.right - m_UpLeft.left);
+ for (col = 0; col < num_columns; col++) {
+ m_Image->m_Surface->DisplayTrans(xxx, Y, m_UpMiddle);
+ m_Image->m_Surface->DisplayTrans(xxx, Y + (m_UpMiddle.bottom - m_UpMiddle.top) + num_rows * tile_height, m_DownMiddle);
+ xxx += tile_width;
+ }
+
+ // tiles
+ yyy = Y + (m_UpMiddle.bottom - m_UpMiddle.top);
+ for (row = 0; row < num_rows; row++) {
+ xxx = X + (m_UpLeft.right - m_UpLeft.left);
+ for (col = 0; col < num_columns; col++) {
+ m_Image->m_Surface->DisplayTrans(xxx, yyy, m_MiddleMiddle);
+ xxx += tile_width;
+ }
+ yyy += tile_width;
+ }
+
+ Game->m_Renderer->EndSpriteBatch();
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::LoadFile(char *Filename) {
+ byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUITiledImage::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ m_Filename = new char [strlen(Filename) + 1];
+ strcpy(m_Filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing TILED_IMAGE file '%s'", Filename);
+
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(TILED_IMAGE)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(UP_LEFT)
+TOKEN_DEF(UP_RIGHT)
+TOKEN_DEF(UP_MIDDLE)
+TOKEN_DEF(DOWN_LEFT)
+TOKEN_DEF(DOWN_RIGHT)
+TOKEN_DEF(DOWN_MIDDLE)
+TOKEN_DEF(MIDDLE_LEFT)
+TOKEN_DEF(MIDDLE_RIGHT)
+TOKEN_DEF(MIDDLE_MIDDLE)
+TOKEN_DEF(VERTICAL_TILES)
+TOKEN_DEF(HORIZONTAL_TILES)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(TILED_IMAGE)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(UP_LEFT)
+ TOKEN_TABLE(UP_RIGHT)
+ TOKEN_TABLE(UP_MIDDLE)
+ TOKEN_TABLE(DOWN_LEFT)
+ TOKEN_TABLE(DOWN_RIGHT)
+ TOKEN_TABLE(DOWN_MIDDLE)
+ TOKEN_TABLE(MIDDLE_LEFT)
+ TOKEN_TABLE(MIDDLE_RIGHT)
+ TOKEN_TABLE(MIDDLE_MIDDLE)
+ TOKEN_TABLE(VERTICAL_TILES)
+ TOKEN_TABLE(HORIZONTAL_TILES)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd;
+ CBParser parser(Game);
+ bool HTiles = false, VTiles = false;
+ int H1 = 0, H2 = 0, H3 = 0;
+ int V1 = 0, V2 = 0, V3 = 0;
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_TILED_IMAGE) {
+ Game->LOG(0, "'TILED_IMAGE' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_IMAGE:
+ SAFE_DELETE(m_Image);
+ m_Image = new CBSubFrame(Game);
+ if (!m_Image || FAILED(m_Image->SetSurface((char *)params))) {
+ SAFE_DELETE(m_Image);
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_UP_LEFT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_UpLeft.left, &m_UpLeft.top, &m_UpLeft.right, &m_UpLeft.bottom);
+ break;
+
+ case TOKEN_UP_RIGHT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_UpRight.left, &m_UpRight.top, &m_UpRight.right, &m_UpRight.bottom);
+ break;
+
+ case TOKEN_UP_MIDDLE:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_UpMiddle.left, &m_UpMiddle.top, &m_UpMiddle.right, &m_UpMiddle.bottom);
+ break;
+
+ case TOKEN_DOWN_LEFT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_DownLeft.left, &m_DownLeft.top, &m_DownLeft.right, &m_DownLeft.bottom);
+ break;
+
+ case TOKEN_DOWN_RIGHT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_DownRight.left, &m_DownRight.top, &m_DownRight.right, &m_DownRight.bottom);
+ break;
+
+ case TOKEN_DOWN_MIDDLE:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_DownMiddle.left, &m_DownMiddle.top, &m_DownMiddle.right, &m_DownMiddle.bottom);
+ break;
+
+ case TOKEN_MIDDLE_LEFT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_MiddleLeft.left, &m_MiddleLeft.top, &m_MiddleLeft.right, &m_MiddleLeft.bottom);
+ break;
+
+ case TOKEN_MIDDLE_RIGHT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_MiddleRight.left, &m_MiddleRight.top, &m_MiddleRight.right, &m_MiddleRight.bottom);
+ break;
+
+ case TOKEN_MIDDLE_MIDDLE:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_MiddleMiddle.left, &m_MiddleMiddle.top, &m_MiddleMiddle.right, &m_MiddleMiddle.bottom);
+ break;
+
+ case TOKEN_HORIZONTAL_TILES:
+ parser.ScanStr((char *)params, "%d,%d,%d", &H1, &H2, &H3);
+ HTiles = true;
+ break;
+
+ case TOKEN_VERTICAL_TILES:
+ parser.ScanStr((char *)params, "%d,%d,%d", &V1, &V2, &V3);
+ VTiles = true;
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in TILED_IMAGE definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading TILED_IMAGE definition");
+ return E_FAIL;
+ }
+
+ if (VTiles && HTiles) {
+ // up row
+ CBPlatform::SetRect(&m_UpLeft, 0, 0, H1, V1);
+ CBPlatform::SetRect(&m_UpMiddle, H1, 0, H1 + H2, V1);
+ CBPlatform::SetRect(&m_UpRight, H1 + H2, 0, H1 + H2 + H3, V1);
+
+ // middle row
+ CBPlatform::SetRect(&m_MiddleLeft, 0, V1, H1, V1 + V2);
+ CBPlatform::SetRect(&m_MiddleMiddle, H1, V1, H1 + H2, V1 + V2);
+ CBPlatform::SetRect(&m_MiddleRight, H1 + H2, V1, H1 + H2 + H3, V1 + V2);
+
+ // down row
+ CBPlatform::SetRect(&m_DownLeft, 0, V1 + V2, H1, V1 + V2 + V3);
+ CBPlatform::SetRect(&m_DownMiddle, H1, V1 + V2, H1 + H2, V1 + V2 + V3);
+ CBPlatform::SetRect(&m_DownRight, H1 + H2, V1 + V2, H1 + H2 + H3, V1 + V2 + V3);
+ }
+
+ // default
+ if (m_Image && m_Image->m_Surface) {
+ int Width = m_Image->m_Surface->GetWidth() / 3;
+ int Height = m_Image->m_Surface->GetHeight() / 3;
+
+ if (CBPlatform::IsRectEmpty(&m_UpLeft)) CBPlatform::SetRect(&m_UpLeft, 0, 0, Width, Height);
+ if (CBPlatform::IsRectEmpty(&m_UpMiddle)) CBPlatform::SetRect(&m_UpMiddle, Width, 0, 2 * Width, Height);
+ if (CBPlatform::IsRectEmpty(&m_UpRight)) CBPlatform::SetRect(&m_UpRight, 2 * Width, 0, 3 * Width, Height);
+
+ if (CBPlatform::IsRectEmpty(&m_MiddleLeft)) CBPlatform::SetRect(&m_MiddleLeft, 0, Height, Width, 2 * Height);
+ if (CBPlatform::IsRectEmpty(&m_MiddleMiddle)) CBPlatform::SetRect(&m_MiddleMiddle, Width, Height, 2 * Width, 2 * Height);
+ if (CBPlatform::IsRectEmpty(&m_MiddleRight)) CBPlatform::SetRect(&m_MiddleRight, 2 * Width, Height, 3 * Width, 2 * Height);
+
+ if (CBPlatform::IsRectEmpty(&m_DownLeft)) CBPlatform::SetRect(&m_DownLeft, 0, 2 * Height, Width, 3 * Height);
+ if (CBPlatform::IsRectEmpty(&m_DownMiddle)) CBPlatform::SetRect(&m_DownMiddle, Width, 2 * Height, 2 * Width, 3 * Height);
+ if (CBPlatform::IsRectEmpty(&m_DownRight)) CBPlatform::SetRect(&m_DownRight, 2 * Width, 2 * Height, 3 * Width, 3 * Height);
+ }
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "TILED_IMAGE\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ if (m_Image && m_Image->m_SurfaceFilename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", m_Image->m_SurfaceFilename);
+
+ int H1, H2, H3;
+ int V1, V2, V3;
+
+ H1 = m_UpLeft.right;
+ H2 = m_UpMiddle.right - m_UpMiddle.left;
+ H3 = m_UpRight.right - m_UpRight.left;
+
+ V1 = m_UpLeft.bottom;
+ V2 = m_MiddleLeft.bottom - m_MiddleLeft.top;
+ V3 = m_DownLeft.bottom - m_DownLeft.top;
+
+
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_TILES { %d, %d, %d }\n", V1, V2, V3);
+ Buffer->PutTextIndent(Indent + 2, "HORIZONTAL_TILES { %d, %d, %d }\n", H1, H2, H3);
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CUITiledImage::CorrectSize(int *Width, int *Height) {
+ int tile_width = m_MiddleMiddle.right - m_MiddleMiddle.left;
+ int tile_height = m_MiddleMiddle.bottom - m_MiddleMiddle.top;
+
+ int num_columns = (*Width - (m_MiddleLeft.right - m_MiddleLeft.left) - (m_MiddleRight.right - m_MiddleRight.left)) / tile_width;
+ int num_rows = (*Height - (m_UpMiddle.bottom - m_UpMiddle.top) - (m_DownMiddle.bottom - m_DownMiddle.top)) / tile_height;
+
+ *Width = (m_MiddleLeft.right - m_MiddleLeft.left) + (m_MiddleRight.right - m_MiddleRight.left) + num_columns * tile_width;
+ *Height = (m_UpMiddle.bottom - m_UpMiddle.top) + (m_DownMiddle.bottom - m_DownMiddle.top) + num_rows * tile_height;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::Persist(CBPersistMgr *PersistMgr) {
+ CBObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(m_DownLeft));
+ PersistMgr->Transfer(TMEMBER(m_DownMiddle));
+ PersistMgr->Transfer(TMEMBER(m_DownRight));
+ PersistMgr->Transfer(TMEMBER(m_Image));
+ PersistMgr->Transfer(TMEMBER(m_MiddleLeft));
+ PersistMgr->Transfer(TMEMBER(m_MiddleMiddle));
+ PersistMgr->Transfer(TMEMBER(m_MiddleRight));
+ PersistMgr->Transfer(TMEMBER(m_UpLeft));
+ PersistMgr->Transfer(TMEMBER(m_UpMiddle));
+ PersistMgr->Transfer(TMEMBER(m_UpRight));
+
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UITiledImage.h b/engines/wintermute/UITiledImage.h
new file mode 100644
index 0000000000..e97b27f59e
--- /dev/null
+++ b/engines/wintermute/UITiledImage.h
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UITILEDIMAGE_H
+#define WINTERMUTE_UITILEDIMAGE_H
+
+
+#include "UIObject.h"
+
+namespace WinterMute {
+class CBSubFrame;
+class CUITiledImage : public CBObject {
+public:
+ DECLARE_PERSISTENT(CUITiledImage, CBObject)
+ void CorrectSize(int *Width, int *Height);
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ HRESULT Display(int X, int Y, int Width, int Height);
+ CUITiledImage(CBGame *inGame = NULL);
+ virtual ~CUITiledImage();
+ CBSubFrame *m_Image;
+ RECT m_UpLeft;
+ RECT m_UpMiddle;
+ RECT m_UpRight;
+ RECT m_MiddleLeft;
+ RECT m_MiddleMiddle;
+ RECT m_MiddleRight;
+ RECT m_DownLeft;
+ RECT m_DownMiddle;
+ RECT m_DownRight;
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UIWindow.cpp b/engines/wintermute/UIWindow.cpp
new file mode 100644
index 0000000000..b68f788fcc
--- /dev/null
+++ b/engines/wintermute/UIWindow.cpp
@@ -0,0 +1,1309 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "dcgf.h"
+#include "UIWindow.h"
+#include "BGame.h"
+#include "BParser.h"
+#include "BActiveRect.h"
+#include "BDynBuffer.h"
+#include "BKeyboardState.h"
+#include "ScValue.h"
+#include "UIButton.h"
+#include "UIEdit.h"
+#include "UIText.h"
+#include "UITiledImage.h"
+#include "BViewport.h"
+#include "BFontStorage.h"
+#include "BFont.h"
+#include "BStringTable.h"
+#include "ScScript.h"
+#include "ScStack.h"
+#include "BSprite.h"
+#include "BFileManager.h"
+#include "PlatformSDL.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIWindow, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIWindow::CUIWindow(CBGame *inGame): CUIObject(inGame) {
+ CBPlatform::SetRectEmpty(&m_TitleRect);
+ CBPlatform::SetRectEmpty(&m_DragRect);
+ m_TitleAlign = TAL_LEFT;
+ m_Transparent = false;
+
+ m_BackInactive = NULL;
+ m_FontInactive = NULL;
+ m_ImageInactive = NULL;
+
+ m_Type = UI_WINDOW;
+ m_CanFocus = true;
+
+ m_Dragging = false;
+ m_DragFrom.x = m_DragFrom.y = 0;
+
+ m_Mode = WINDOW_NORMAL;
+ m_ShieldWindow = NULL;
+ m_ShieldButton = NULL;
+
+ m_FadeColor = 0x00000000;
+ m_FadeBackground = false;
+
+ m_Ready = true;
+ m_IsMenu = false;
+ m_InGame = false;
+
+ m_ClipContents = false;
+ m_Viewport = NULL;
+
+ m_PauseMusic = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIWindow::~CUIWindow() {
+ Close();
+ Cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIWindow::Cleanup() {
+ delete m_ShieldWindow;
+ delete m_ShieldButton;
+ delete m_Viewport;
+ m_ShieldWindow = NULL;
+ m_ShieldButton = NULL;
+ m_Viewport = NULL;
+
+ if (m_BackInactive) delete m_BackInactive;
+ if (!m_SharedFonts && m_FontInactive) Game->m_FontStorage->RemoveFont(m_FontInactive);
+ if (!m_SharedImages && m_ImageInactive) delete m_ImageInactive;
+
+ for (int i = 0; i < m_Widgets.GetSize(); i++) delete m_Widgets[i];
+ m_Widgets.RemoveAll();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Display(int OffsetX, int OffsetY) {
+ // go exclusive
+ if (m_Mode == WINDOW_EXCLUSIVE || m_Mode == WINDOW_SYSTEM_EXCLUSIVE) {
+ if (!m_ShieldWindow) m_ShieldWindow = new CUIWindow(Game);
+ if (m_ShieldWindow) {
+ m_ShieldWindow->m_PosX = m_ShieldWindow->m_PosY = 0;
+ m_ShieldWindow->m_Width = Game->m_Renderer->m_Width;
+ m_ShieldWindow->m_Height = Game->m_Renderer->m_Height;
+
+ m_ShieldWindow->Display();
+ }
+ } else if (m_IsMenu) {
+ if (!m_ShieldButton) {
+ m_ShieldButton = new CUIButton(Game);
+ m_ShieldButton->SetName("close");
+ m_ShieldButton->SetListener(this, m_ShieldButton, 0);
+ m_ShieldButton->m_Parent = this;
+ }
+ if (m_ShieldButton) {
+ m_ShieldButton->m_PosX = m_ShieldButton->m_PosY = 0;
+ m_ShieldButton->m_Width = Game->m_Renderer->m_Width;
+ m_ShieldButton->m_Height = Game->m_Renderer->m_Height;
+
+ m_ShieldButton->Display();
+ }
+ }
+
+ if (!m_Visible) return S_OK;
+
+ if (m_FadeBackground) Game->m_Renderer->FadeToColor(m_FadeColor);
+
+ if (m_Dragging) {
+ m_PosX += (Game->m_MousePos.x - m_DragFrom.x);
+ m_PosY += (Game->m_MousePos.y - m_DragFrom.y);
+
+ m_DragFrom.x = Game->m_MousePos.x;
+ m_DragFrom.y = Game->m_MousePos.y;
+ }
+
+ if (!m_FocusedWidget || (!m_FocusedWidget->m_CanFocus || m_FocusedWidget->m_Disable || !m_FocusedWidget->m_Visible)) {
+ MoveFocus();
+ }
+
+ bool PopViewport = false;
+ if (m_ClipContents) {
+ if (!m_Viewport) m_Viewport = new CBViewport(Game);
+ if (m_Viewport) {
+ m_Viewport->SetRect(m_PosX + OffsetX, m_PosY + OffsetY, m_PosX + m_Width + OffsetX, m_PosY + m_Height + OffsetY);
+ Game->PushViewport(m_Viewport);
+ PopViewport = true;
+ }
+ }
+
+
+ CUITiledImage *back = m_Back;
+ CBSprite *image = m_Image;
+ CBFont *font = m_Font;
+
+ if (!IsFocused()) {
+ if (m_BackInactive) back = m_BackInactive;
+ if (m_ImageInactive) image = m_ImageInactive;
+ if (m_FontInactive) font = m_FontInactive;
+ }
+
+ if (m_AlphaColor != 0) Game->m_Renderer->m_ForceAlphaColor = m_AlphaColor;
+ if (back) back->Display(m_PosX + OffsetX, m_PosY + OffsetY, m_Width, m_Height);
+ if (image) image->Draw(m_PosX + OffsetX, m_PosY + OffsetY, m_Transparent ? NULL : this);
+
+ if (!CBPlatform::IsRectEmpty(&m_TitleRect) && font && m_Text) {
+ font->DrawText((byte *)m_Text, m_PosX + OffsetX + m_TitleRect.left, m_PosY + OffsetY + m_TitleRect.top, m_TitleRect.right - m_TitleRect.left, m_TitleAlign, m_TitleRect.bottom - m_TitleRect.top);
+ }
+
+ if (!m_Transparent && !image) Game->m_Renderer->m_RectList.Add(new CBActiveRect(Game, this, NULL, m_PosX + OffsetX, m_PosY + OffsetY, m_Width, m_Height, 100, 100, false));
+
+ for (int i = 0; i < m_Widgets.GetSize(); i++) {
+ m_Widgets[i]->Display(m_PosX + OffsetX, m_PosY + OffsetY);
+ }
+
+ if (m_AlphaColor != 0) Game->m_Renderer->m_ForceAlphaColor = 0;
+
+ if (PopViewport) Game->PopViewport();
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::LoadFile(char *Filename) {
+ byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIWindow::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ m_Filename = new char [strlen(Filename) + 1];
+ strcpy(m_Filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing WINDOW file '%s'", Filename);
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(WINDOW)
+TOKEN_DEF(ALPHA_COLOR)
+TOKEN_DEF(ALPHA)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(BACK_INACTIVE)
+TOKEN_DEF(BACK)
+TOKEN_DEF(IMAGE_INACTIVE)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT_INACTIVE)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TITLE_ALIGN)
+TOKEN_DEF(TITLE_RECT)
+TOKEN_DEF(TITLE)
+TOKEN_DEF(DRAG_RECT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(FADE_ALPHA)
+TOKEN_DEF(FADE_COLOR)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(NAME)
+TOKEN_DEF(BUTTON)
+TOKEN_DEF(STATIC)
+TOKEN_DEF(TRANSPARENT)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(MENU)
+TOKEN_DEF(IN_GAME)
+TOKEN_DEF(CLIP_CONTENTS)
+TOKEN_DEF(PAUSE_MUSIC)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(EDIT)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(WINDOW)
+ TOKEN_TABLE(ALPHA_COLOR)
+ TOKEN_TABLE(ALPHA)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(BACK_INACTIVE)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(IMAGE_INACTIVE)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT_INACTIVE)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TITLE_ALIGN)
+ TOKEN_TABLE(TITLE_RECT)
+ TOKEN_TABLE(TITLE)
+ TOKEN_TABLE(DRAG_RECT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(FADE_ALPHA)
+ TOKEN_TABLE(FADE_COLOR)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(BUTTON)
+ TOKEN_TABLE(STATIC)
+ TOKEN_TABLE(TRANSPARENT)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(MENU)
+ TOKEN_TABLE(IN_GAME)
+ TOKEN_TABLE(CLIP_CONTENTS)
+ TOKEN_TABLE(PAUSE_MUSIC)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(EDIT)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ int FadeR = 0, FadeG = 0, FadeB = 0, FadeA = 0;
+ int ar = 0, ag = 0, ab = 0, alpha = 0;
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_WINDOW) {
+ Game->LOG(0, "'WINDOW' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd >= PARSERR_TOKENNOTFOUND && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) >= PARSERR_TOKENNOTFOUND) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ SAFE_DELETE(m_Back);
+ m_Back = new CUITiledImage(Game);
+ if (!m_Back || FAILED(m_Back->LoadFile((char *)params))) {
+ SAFE_DELETE(m_Back);
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_INACTIVE:
+ SAFE_DELETE(m_BackInactive);
+ m_BackInactive = new CUITiledImage(Game);
+ if (!m_BackInactive || FAILED(m_BackInactive->LoadFile((char *)params))) {
+ SAFE_DELETE(m_BackInactive);
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ SAFE_DELETE(m_Image);
+ m_Image = new CBSprite(Game);
+ if (!m_Image || FAILED(m_Image->LoadFile((char *)params))) {
+ SAFE_DELETE(m_Image);
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_INACTIVE:
+ SAFE_DELETE(m_ImageInactive),
+ m_ImageInactive = new CBSprite(Game);
+ if (!m_ImageInactive || FAILED(m_ImageInactive->LoadFile((char *)params))) {
+ SAFE_DELETE(m_ImageInactive);
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
+ m_Font = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_Font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_INACTIVE:
+ if (m_FontInactive) Game->m_FontStorage->RemoveFont(m_FontInactive);
+ m_FontInactive = Game->m_FontStorage->AddFont((char *)params);
+ if (!m_FontInactive) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TITLE:
+ SetText((char *)params);
+ Game->m_StringTable->Expand(&m_Text);
+ break;
+
+ case TOKEN_TITLE_ALIGN:
+ if (scumm_stricmp((char *)params, "left") == 0) m_TitleAlign = TAL_LEFT;
+ else if (scumm_stricmp((char *)params, "right") == 0) m_TitleAlign = TAL_RIGHT;
+ else m_TitleAlign = TAL_CENTER;
+ break;
+
+ case TOKEN_TITLE_RECT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_TitleRect.left, &m_TitleRect.top, &m_TitleRect.right, &m_TitleRect.bottom);
+ break;
+
+ case TOKEN_DRAG_RECT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &m_DragRect.left, &m_DragRect.top, &m_DragRect.right, &m_DragRect.bottom);
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &m_PosX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &m_PosY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &m_Width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &m_Height);
+ break;
+
+ case TOKEN_CURSOR:
+ SAFE_DELETE(m_Cursor);
+ m_Cursor = new CBSprite(Game);
+ if (!m_Cursor || FAILED(m_Cursor->LoadFile((char *)params))) {
+ SAFE_DELETE(m_Cursor);
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BUTTON: {
+ CUIButton *btn = new CUIButton(Game);
+ if (!btn || FAILED(btn->LoadBuffer(params, false))) {
+ SAFE_DELETE(btn);
+ cmd = PARSERR_GENERIC;
+ } else {
+ btn->m_Parent = this;
+ m_Widgets.Add(btn);
+ }
+ }
+ break;
+
+ case TOKEN_STATIC: {
+ CUIText *text = new CUIText(Game);
+ if (!text || FAILED(text->LoadBuffer(params, false))) {
+ SAFE_DELETE(text);
+ cmd = PARSERR_GENERIC;
+ } else {
+ text->m_Parent = this;
+ m_Widgets.Add(text);
+ }
+ }
+ break;
+
+ case TOKEN_EDIT: {
+ CUIEdit *edit = new CUIEdit(Game);
+ if (!edit || FAILED(edit->LoadBuffer(params, false))) {
+ SAFE_DELETE(edit);
+ cmd = PARSERR_GENERIC;
+ } else {
+ edit->m_Parent = this;
+ m_Widgets.Add(edit);
+ }
+ }
+ break;
+
+ case TOKEN_WINDOW: {
+ CUIWindow *win = new CUIWindow(Game);
+ if (!win || FAILED(win->LoadBuffer(params, false))) {
+ SAFE_DELETE(win);
+ cmd = PARSERR_GENERIC;
+ } else {
+ win->m_Parent = this;
+ m_Widgets.Add(win);
+ }
+ }
+ break;
+
+
+ case TOKEN_TRANSPARENT:
+ parser.ScanStr((char *)params, "%b", &m_Transparent);
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &m_ParentNotify);
+ break;
+
+ case TOKEN_PAUSE_MUSIC:
+ parser.ScanStr((char *)params, "%b", &m_PauseMusic);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &m_Disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &m_Visible);
+ break;
+
+ case TOKEN_MENU:
+ parser.ScanStr((char *)params, "%b", &m_IsMenu);
+ break;
+
+ case TOKEN_IN_GAME:
+ parser.ScanStr((char *)params, "%b", &m_InGame);
+ break;
+
+ case TOKEN_CLIP_CONTENTS:
+ parser.ScanStr((char *)params, "%b", &m_ClipContents);
+ break;
+
+ case TOKEN_FADE_COLOR:
+ parser.ScanStr((char *)params, "%d,%d,%d", &FadeR, &FadeG, &FadeB);
+ m_FadeBackground = true;
+ break;
+
+ case TOKEN_FADE_ALPHA:
+ parser.ScanStr((char *)params, "%d", &FadeA);
+ m_FadeBackground = true;
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+
+ case TOKEN_ALPHA_COLOR:
+ parser.ScanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ break;
+
+ case TOKEN_ALPHA:
+ parser.ScanStr((char *)params, "%d", &alpha);
+ break;
+
+
+ default:
+ if (FAILED(Game->WindowLoadHook(this, (char **)&Buffer, (char **)params))) {
+ cmd = PARSERR_GENERIC;
+ }
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in WINDOW definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading WINDOW definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) {
+ ar = ag = ab = 255;
+ }
+ m_AlphaColor = DRGBA(ar, ag, ab, alpha);
+
+ if (m_FadeBackground) m_FadeColor = DRGBA(FadeR, FadeG, FadeB, FadeA);
+
+ m_FocusedWidget = NULL;
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "WINDOW\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Back && m_Back->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", m_Back->m_Filename);
+ if (m_BackInactive && m_BackInactive->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_INACTIVE=\"%s\"\n", m_BackInactive->m_Filename);
+
+ if (m_Image && m_Image->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", m_Image->m_Filename);
+ if (m_ImageInactive && m_ImageInactive->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_INACTIVE=\"%s\"\n", m_ImageInactive->m_Filename);
+
+ if (m_Font && m_Font->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", m_Font->m_Filename);
+ if (m_FontInactive && m_FontInactive->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_INACTIVE=\"%s\"\n", m_FontInactive->m_Filename);
+
+ if (m_Cursor && m_Cursor->m_Filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", m_Cursor->m_Filename);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_Text)
+ Buffer->PutTextIndent(Indent + 2, "TITLE=\"%s\"\n", m_Text);
+
+ switch (m_TitleAlign) {
+ case TAL_LEFT:
+ Buffer->PutTextIndent(Indent + 2, "TITLE_ALIGN=\"%s\"\n", "left");
+ break;
+ case TAL_RIGHT:
+ Buffer->PutTextIndent(Indent + 2, "TITLE_ALIGN=\"%s\"\n", "right");
+ break;
+ case TAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "TITLE_ALIGN=\"%s\"\n", "center");
+ break;
+ }
+
+ if (!CBPlatform::IsRectEmpty(&m_TitleRect)) {
+ Buffer->PutTextIndent(Indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", m_TitleRect.left, m_TitleRect.top, m_TitleRect.right, m_TitleRect.bottom);
+ }
+
+ if (!CBPlatform::IsRectEmpty(&m_DragRect)) {
+ Buffer->PutTextIndent(Indent + 2, "DRAG_RECT { %d, %d, %d, %d }\n", m_DragRect.left, m_DragRect.top, m_DragRect.right, m_DragRect.bottom);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", m_PosX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", m_PosY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", m_Width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", m_Height);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", m_Disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", m_Visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", m_ParentNotify ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "TRANSPARENT=%s\n", m_Transparent ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PAUSE_MUSIC=%s\n", m_PauseMusic ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "MENU=%s\n", m_IsMenu ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "IN_GAME=%s\n", m_InGame ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "CLIP_CONTENTS=%s\n", m_ClipContents ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (m_FadeBackground) {
+ Buffer->PutTextIndent(Indent + 2, "FADE_COLOR { %d, %d, %d }\n", D3DCOLGetR(m_FadeColor), D3DCOLGetG(m_FadeColor), D3DCOLGetB(m_FadeColor));
+ Buffer->PutTextIndent(Indent + 2, "FADE_ALPHA=%d\n", D3DCOLGetA(m_FadeColor));
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "ALPHA_COLOR { %d, %d, %d }\n", D3DCOLGetR(m_AlphaColor), D3DCOLGetG(m_AlphaColor), D3DCOLGetB(m_AlphaColor));
+ Buffer->PutTextIndent(Indent + 2, "ALPHA=%d\n", D3DCOLGetA(m_AlphaColor));
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < m_Scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ // controls
+ for (int i = 0; i < m_Widgets.GetSize(); i++)
+ m_Widgets[i]->SaveAsText(Buffer, Indent + 2);
+
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::EnableWidget(char *Name, bool Enable) {
+ for (int i = 0; i < m_Widgets.GetSize(); i++) {
+ if (scumm_stricmp(m_Widgets[i]->m_Name, Name) == 0) m_Widgets[i]->m_Disable = !Enable;
+ }
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::ShowWidget(char *Name, bool Visible) {
+ for (int i = 0; i < m_Widgets.GetSize(); i++) {
+ if (scumm_stricmp(m_Widgets[i]->m_Name, Name) == 0) m_Widgets[i]->m_Visible = Visible;
+ }
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // GetWidget / GetControl
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "GetWidget") == 0 || strcmp(Name, "GetControl") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *val = Stack->Pop();
+ if (val->GetType() == VAL_INT) {
+ int widget = val->GetInt();
+ if (widget < 0 || widget >= m_Widgets.GetSize()) Stack->PushNULL();
+ else Stack->PushNative(m_Widgets[widget], true);
+ } else {
+ for (int i = 0; i < m_Widgets.GetSize(); i++) {
+ if (scumm_stricmp(m_Widgets[i]->m_Name, val->GetString()) == 0) {
+ Stack->PushNative(m_Widgets[i], true);
+ return S_OK;
+ }
+ }
+ Stack->PushNULL();
+ }
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetInactiveFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetInactiveFont") == 0) {
+ Stack->CorrectParams(1);
+
+ if (m_FontInactive) Game->m_FontStorage->RemoveFont(m_FontInactive);
+ m_FontInactive = Game->m_FontStorage->AddFont(Stack->Pop()->GetString());
+ Stack->PushBool(m_FontInactive != NULL);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetInactiveImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetInactiveImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete m_ImageInactive;
+ m_ImageInactive = new CBSprite(Game);
+ char *Filename = Stack->Pop()->GetString();
+ if (!m_ImageInactive || FAILED(m_ImageInactive->LoadFile(Filename))) {
+ delete m_ImageInactive;
+ m_ImageInactive = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetInactiveImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetInactiveImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageInactive || !m_ImageInactive->m_Filename) Stack->PushNULL();
+ else Stack->PushString(m_ImageInactive->m_Filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetInactiveImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetInactiveImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!m_ImageInactive) Stack->PushNULL();
+ else Stack->PushNative(m_ImageInactive, true);
+
+ return S_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Close
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Close") == 0) {
+ Stack->CorrectParams(0);
+ Stack->PushBool(SUCCEEDED(Close()));
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GoExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GoExclusive") == 0) {
+ Stack->CorrectParams(0);
+ GoExclusive();
+ Script->WaitFor(this);
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GoSystemExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GoSystemExclusive") == 0) {
+ Stack->CorrectParams(0);
+ GoSystemExclusive();
+ Script->WaitFor(this);
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Center
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Center") == 0) {
+ Stack->CorrectParams(0);
+ m_PosX = (Game->m_Renderer->m_Width - m_Width) / 2;
+ m_PosY = (Game->m_Renderer->m_Height - m_Height) / 2;
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LoadFromFile
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "LoadFromFile") == 0) {
+ Stack->CorrectParams(1);
+
+ CScValue *Val = Stack->Pop();
+ Cleanup();
+ if (!Val->IsNULL()) {
+ Stack->PushBool(SUCCEEDED(LoadFile(Val->GetString())));
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateButton
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateButton") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIButton *Btn = new CUIButton(Game);
+ if (!Val->IsNULL()) Btn->SetName(Val->GetString());
+ Stack->PushNative(Btn, true);
+
+ Btn->m_Parent = this;
+ m_Widgets.Add(Btn);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateStatic
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateStatic") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIText *Sta = new CUIText(Game);
+ if (!Val->IsNULL()) Sta->SetName(Val->GetString());
+ Stack->PushNative(Sta, true);
+
+ Sta->m_Parent = this;
+ m_Widgets.Add(Sta);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateEditor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateEditor") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIEdit *Edi = new CUIEdit(Game);
+ if (!Val->IsNULL()) Edi->SetName(Val->GetString());
+ Stack->PushNative(Edi, true);
+
+ Edi->m_Parent = this;
+ m_Widgets.Add(Edi);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateWindow") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIWindow *Win = new CUIWindow(Game);
+ if (!Val->IsNULL()) Win->SetName(Val->GetString());
+ Stack->PushNative(Win, true);
+
+ Win->m_Parent = this;
+ m_Widgets.Add(Win);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteControl / DeleteButton / DeleteStatic / DeleteEditor / DeleteWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "DeleteControl") == 0 || strcmp(Name, "DeleteButton") == 0 || strcmp(Name, "DeleteStatic") == 0 || strcmp(Name, "DeleteEditor") == 0 || strcmp(Name, "DeleteWindow") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *val = Stack->Pop();
+ CUIObject *obj = (CUIObject *)val->GetNative();
+
+ for (int i = 0; i < m_Widgets.GetSize(); i++) {
+ if (m_Widgets[i] == obj) {
+ delete m_Widgets[i];
+ m_Widgets.RemoveAt(i);
+ if (val->GetType() == VAL_VARIABLE_REF) val->SetNULL();
+ }
+ }
+ Stack->PushNULL();
+ return S_OK;
+ } else if SUCCEEDED(Game->WindowScriptMethodHook(this, Script, Stack, Name)) return S_OK;
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIWindow::ScGetProperty(char *Name) {
+ m_ScValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ m_ScValue->SetString("window");
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NumWidgets / NumControls (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "NumWidgets") == 0 || strcmp(Name, "NumControls") == 0) {
+ m_ScValue->SetInt(m_Widgets.GetSize());
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Exclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Exclusive") == 0) {
+ m_ScValue->SetBool(m_Mode == WINDOW_EXCLUSIVE);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SystemExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SystemExclusive") == 0) {
+ m_ScValue->SetBool(m_Mode == WINDOW_SYSTEM_EXCLUSIVE);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Menu
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Menu") == 0) {
+ m_ScValue->SetBool(m_IsMenu);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "InGame") == 0) {
+ m_ScValue->SetBool(m_InGame);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseMusic
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PauseMusic") == 0) {
+ m_ScValue->SetBool(m_PauseMusic);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ClipContents
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ClipContents") == 0) {
+ m_ScValue->SetBool(m_ClipContents);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Transparent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Transparent") == 0) {
+ m_ScValue->SetBool(m_Transparent);
+ return m_ScValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FadeColor") == 0) {
+ m_ScValue->SetInt((int)m_FadeColor);
+ return m_ScValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::ScSetProperty(char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Name") == 0) {
+ SetName(Value->GetString());
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Menu
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Menu") == 0) {
+ m_IsMenu = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "InGame") == 0) {
+ m_InGame = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseMusic
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PauseMusic") == 0) {
+ m_PauseMusic = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ClipContents
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ClipContents") == 0) {
+ m_ClipContents = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Transparent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Transparent") == 0) {
+ m_Transparent = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FadeColor") == 0) {
+ m_FadeColor = (uint32)Value->GetInt();
+ m_FadeBackground = (m_FadeColor != 0);
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Exclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Exclusive") == 0) {
+ if (Value->GetBool())
+ GoExclusive();
+ else {
+ Close();
+ m_Visible = true;
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SystemExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SystemExclusive") == 0) {
+ if (Value->GetBool())
+ GoSystemExclusive();
+ else {
+ Close();
+ m_Visible = true;
+ }
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *CUIWindow::ScToString() {
+ return "[window]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIWindow::HandleKeypress(SDL_Event *event) {
+
+ if (event->type == SDL_KEYDOWN && event->key.keysym.scancode == SDL_SCANCODE_TAB) {
+ return SUCCEEDED(MoveFocus(!CBKeyboardState::IsShiftDown()));
+ } else {
+ if (m_FocusedWidget) return m_FocusedWidget->HandleKeypress(event);
+ else return false;
+ }
+
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIWindow::HandleMouseWheel(int Delta) {
+ if (m_FocusedWidget) return m_FocusedWidget->HandleMouseWheel(Delta);
+ else return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::HandleMouse(TMouseEvent Event, TMouseButton Button) {
+ HRESULT res = CUIObject::HandleMouse(Event, Button);
+
+ // handle window dragging
+ if (!CBPlatform::IsRectEmpty(&m_DragRect)) {
+ // start drag
+ if (Event == MOUSE_CLICK && Button == MOUSE_BUTTON_LEFT) {
+ RECT DragRect = m_DragRect;
+ int OffsetX, OffsetY;
+ GetTotalOffset(&OffsetX, &OffsetY);
+ CBPlatform::OffsetRect(&DragRect, m_PosX + OffsetX, m_PosY + OffsetY);
+
+ if (CBPlatform::PtInRect(&DragRect, Game->m_MousePos)) {
+ m_DragFrom.x = Game->m_MousePos.x;
+ m_DragFrom.y = Game->m_MousePos.y;
+ m_Dragging = true;
+ }
+ }
+ // end drag
+ else if (m_Dragging && Event == MOUSE_RELEASE && Button == MOUSE_BUTTON_LEFT) {
+ m_Dragging = false;
+ }
+ }
+
+ return res;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(m_BackInactive));
+ PersistMgr->Transfer(TMEMBER(m_ClipContents));
+ PersistMgr->Transfer(TMEMBER(m_DragFrom));
+ PersistMgr->Transfer(TMEMBER(m_Dragging));
+ PersistMgr->Transfer(TMEMBER(m_DragRect));
+ PersistMgr->Transfer(TMEMBER(m_FadeBackground));
+ PersistMgr->Transfer(TMEMBER(m_FadeColor));
+ PersistMgr->Transfer(TMEMBER(m_FontInactive));
+ PersistMgr->Transfer(TMEMBER(m_ImageInactive));
+ PersistMgr->Transfer(TMEMBER(m_InGame));
+ PersistMgr->Transfer(TMEMBER(m_IsMenu));
+ PersistMgr->Transfer(TMEMBER_INT(m_Mode));
+ PersistMgr->Transfer(TMEMBER(m_ShieldButton));
+ PersistMgr->Transfer(TMEMBER(m_ShieldWindow));
+ PersistMgr->Transfer(TMEMBER_INT(m_TitleAlign));
+ PersistMgr->Transfer(TMEMBER(m_TitleRect));
+ PersistMgr->Transfer(TMEMBER(m_Transparent));
+ PersistMgr->Transfer(TMEMBER(m_Viewport));
+ PersistMgr->Transfer(TMEMBER(m_PauseMusic));
+
+ m_Widgets.Persist(PersistMgr);
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::MoveFocus(bool Forward) {
+ int i;
+ bool found = false;
+ for (i = 0; i < m_Widgets.GetSize(); i++) {
+ if (m_Widgets[i] == m_FocusedWidget) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) m_FocusedWidget = NULL;
+
+ if (!m_FocusedWidget) {
+ if (m_Widgets.GetSize() > 0) i = 0;
+ else return S_OK;
+ }
+
+ int NumTries = 0;
+ bool done = false;
+
+ while (NumTries <= m_Widgets.GetSize()) {
+ if (m_Widgets[i] != m_FocusedWidget && m_Widgets[i]->m_CanFocus && m_Widgets[i]->m_Visible && !m_Widgets[i]->m_Disable) {
+ m_FocusedWidget = m_Widgets[i];
+ done = true;
+ break;
+ }
+
+ if (Forward) {
+ i++;
+ if (i >= m_Widgets.GetSize()) i = 0;
+ } else {
+ i--;
+ if (i < 0) i = m_Widgets.GetSize() - 1;
+ }
+ NumTries++;
+ }
+
+ return done ? S_OK : E_FAIL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::GoExclusive() {
+ if (m_Mode == WINDOW_EXCLUSIVE) return S_OK;
+
+ if (m_Mode == WINDOW_NORMAL) {
+ m_Ready = false;
+ m_Mode = WINDOW_EXCLUSIVE;
+ m_Visible = true;
+ m_Disable = false;
+ Game->FocusWindow(this);
+ return S_OK;
+ } else return E_FAIL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::GoSystemExclusive() {
+ if (m_Mode == WINDOW_SYSTEM_EXCLUSIVE) return S_OK;
+
+ MakeFreezable(false);
+
+ m_Mode = WINDOW_SYSTEM_EXCLUSIVE;
+ m_Ready = false;
+ m_Visible = true;
+ m_Disable = false;
+ Game->FocusWindow(this);
+
+ Game->Freeze(m_PauseMusic);
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Close() {
+ if (m_Mode == WINDOW_SYSTEM_EXCLUSIVE) {
+ Game->Unfreeze();
+ }
+
+ m_Mode = WINDOW_NORMAL;
+ m_Visible = false;
+ m_Ready = true;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Listen(CBScriptHolder *param1, uint32 param2) {
+ CUIObject *obj = (CUIObject *)param1;
+
+ switch (obj->m_Type) {
+ case UI_BUTTON:
+ if (scumm_stricmp(obj->m_Name, "close") == 0) Close();
+ else return CBObject::Listen(param1, param2);
+ break;
+ default:
+ return CBObject::Listen(param1, param2);
+ }
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIWindow::MakeFreezable(bool Freezable) {
+ for (int i = 0; i < m_Widgets.GetSize(); i++)
+ m_Widgets[i]->MakeFreezable(Freezable);
+
+ CBObject::MakeFreezable(Freezable);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::GetWindowObjects(CBArray<CUIObject *, CUIObject *>& Objects, bool InteractiveOnly) {
+ for (int i = 0; i < m_Widgets.GetSize(); i++) {
+ CUIObject *Control = m_Widgets[i];
+ if (Control->m_Disable && InteractiveOnly) continue;
+
+ switch (Control->m_Type) {
+ case UI_WINDOW:
+ ((CUIWindow *)Control)->GetWindowObjects(Objects, InteractiveOnly);
+ break;
+
+ case UI_BUTTON:
+ case UI_EDIT:
+ Objects.Add(Control);
+ break;
+
+ default:
+ if (!InteractiveOnly) Objects.Add(Control);
+ }
+ }
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UIWindow.h b/engines/wintermute/UIWindow.h
new file mode 100644
index 0000000000..b8adc2f27f
--- /dev/null
+++ b/engines/wintermute/UIWindow.h
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIWINDOW_H
+#define WINTERMUTE_UIWINDOW_H
+
+
+#include "UIObject.h"
+
+namespace WinterMute {
+
+class CUIButton;
+class CBViewport;
+class CUIWindow : public CUIObject {
+public:
+ HRESULT GetWindowObjects(CBArray<CUIObject *, CUIObject *>& Objects, bool InteractiveOnly);
+
+ bool m_PauseMusic;
+ void Cleanup();
+ virtual void MakeFreezable(bool Freezable);
+ CBViewport *m_Viewport;
+ bool m_ClipContents;
+ bool m_InGame;
+ bool m_IsMenu;
+ bool m_FadeBackground;
+ uint32 m_FadeColor;
+ virtual bool HandleMouseWheel(int Delta);
+ CUIWindow *m_ShieldWindow;
+ CUIButton *m_ShieldButton;
+ HRESULT Close();
+ HRESULT GoSystemExclusive();
+ HRESULT GoExclusive();
+ TWindowMode m_Mode;
+ HRESULT MoveFocus(bool Forward = true);
+ virtual HRESULT HandleMouse(TMouseEvent Event, TMouseButton Button);
+ POINT m_DragFrom;
+ bool m_Dragging;
+ DECLARE_PERSISTENT(CUIWindow, CUIObject)
+ bool m_Transparent;
+ HRESULT ShowWidget(char *Name, bool Visible = true);
+ HRESULT EnableWidget(char *Name, bool Enable = true);
+ RECT m_TitleRect;
+ RECT m_DragRect;
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ CUIWindow(CBGame *inGame);
+ virtual ~CUIWindow();
+ virtual bool HandleKeypress(SDL_Event *event);
+ CBArray<CUIObject *, CUIObject *> m_Widgets;
+ TTextAlign m_TitleAlign;
+ HRESULT LoadFile(char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ CUITiledImage *m_BackInactive;
+ CBFont *m_FontInactive;
+ CBSprite *m_ImageInactive;
+ virtual HRESULT Listen(CBScriptHolder *param1, uint32 param2);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(char *Name);
+ virtual HRESULT ScSetProperty(char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name);
+ virtual char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk
index e6847eb585..a7bac98891 100644
--- a/engines/wintermute/module.mk
+++ b/engines/wintermute/module.mk
@@ -42,6 +42,10 @@ MODULE_OBJS := \
StringUtil.o \
SysClass.o \
SysInstance.o \
+ UIButton.o \
+ UIEntity.o \
+ UIObject.o \
+ UITiledImage.o \
utils.o \
wintermute.o