Initial commit
This commit is contained in:
1217
engines/wintermute/ui/ui_button.cpp
Normal file
1217
engines/wintermute/ui/ui_button.cpp
Normal file
File diff suppressed because it is too large
Load Diff
79
engines/wintermute/ui/ui_button.h
Normal file
79
engines/wintermute/ui/ui_button.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/ui/ui_object.h"
|
||||
#include "engines/wintermute/dctypes.h" // Added by ClassView
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class UIButton : public UIObject {
|
||||
public:
|
||||
bool _pixelPerfect;
|
||||
bool _stayPressed;
|
||||
bool _centerImage;
|
||||
bool _oneTimePress;
|
||||
uint32 _oneTimePressTime{};
|
||||
DECLARE_PERSISTENT(UIButton, UIObject)
|
||||
void press();
|
||||
bool display() override { return display(0, 0); }
|
||||
bool display(int offsetX, int offsetY) override;
|
||||
bool _press;
|
||||
bool _hover;
|
||||
void correctSize() override;
|
||||
TTextAlign _align;
|
||||
BaseSprite *_imageHover;
|
||||
BaseSprite *_imagePress;
|
||||
BaseSprite *_imageDisable;
|
||||
BaseSprite *_imageFocus;
|
||||
BaseFont *_fontDisable;
|
||||
BaseFont *_fontPress;
|
||||
BaseFont *_fontHover;
|
||||
BaseFont *_fontFocus;
|
||||
UITiledImage *_backPress;
|
||||
UITiledImage *_backHover;
|
||||
UITiledImage *_backDisable;
|
||||
UITiledImage *_backFocus;
|
||||
UIButton(BaseGame *inGame = nullptr);
|
||||
~UIButton() override;
|
||||
bool loadFile(const char *filename);
|
||||
bool loadBuffer(char *buffer, bool complete = true);
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
// scripting interface
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
934
engines/wintermute/ui/ui_edit.cpp
Normal file
934
engines/wintermute/ui/ui_edit.cpp
Normal file
@@ -0,0 +1,934 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/ui/ui_edit.h"
|
||||
#include "engines/wintermute/ui/ui_object.h"
|
||||
#include "engines/wintermute/ui/ui_tiled_image.h"
|
||||
#include "engines/wintermute/utils/string_util.h"
|
||||
#include "engines/wintermute/base/base_active_rect.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/base/font/base_font.h"
|
||||
#include "engines/wintermute/base/font/base_font_storage.h"
|
||||
#include "engines/wintermute/base/base_keyboard_state.h"
|
||||
#include "engines/wintermute/base/base_dynamic_buffer.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/base_sprite.h"
|
||||
#include "engines/wintermute/base/base_string_table.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_access_mgr.h"
|
||||
#include "engines/wintermute/base/gfx/base_renderer.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
#include "engines/wintermute/utils/utils.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
#include "common/util.h"
|
||||
#include "common/keyboard.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(UIEdit, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIEdit::UIEdit(BaseGame *inGame) : UIObject(inGame) {
|
||||
_type = UI_EDIT;
|
||||
|
||||
_fontSelected = nullptr;
|
||||
|
||||
_selStart = _selEnd = 10000;
|
||||
_scrollOffset = 0;
|
||||
|
||||
_cursorChar = nullptr;
|
||||
setCursorChar("|");
|
||||
|
||||
_cursorBlinkRate = 600;
|
||||
|
||||
_frameWidth = 0;
|
||||
|
||||
setText("");
|
||||
|
||||
_lastBlinkTime = 0;
|
||||
_cursorVisible = true;
|
||||
|
||||
_maxLength = -1;
|
||||
|
||||
_canFocus = true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIEdit::~UIEdit() {
|
||||
if (!_sharedFonts) {
|
||||
if (_fontSelected) {
|
||||
_game->_fontStorage->removeFont(_fontSelected);
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(_cursorChar);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::loadFile(const char *filename) {
|
||||
char *buffer = (char *)_game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
_game->LOG(0, "UIEdit::loadFile failed for file '%s'", filename);
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
|
||||
setFilename(filename);
|
||||
|
||||
if (DID_FAIL(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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::loadBuffer(char *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
|
||||
|
||||
char *params;
|
||||
int cmd = 2;
|
||||
BaseParser parser(_game);
|
||||
|
||||
if (complete) {
|
||||
if (parser.getCommand(&buffer, commands, ¶ms) != TOKEN_EDIT) {
|
||||
_game->LOG(0, "'EDIT' keyword expected.");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
buffer = params;
|
||||
}
|
||||
|
||||
while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
switch (cmd) {
|
||||
case TOKEN_TEMPLATE:
|
||||
if (DID_FAIL(loadFile(params))) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_NAME:
|
||||
setName(params);
|
||||
break;
|
||||
|
||||
case TOKEN_BACK:
|
||||
SAFE_DELETE(_back);
|
||||
_back = new UITiledImage(_game);
|
||||
if (!_back || DID_FAIL(_back->loadFile(params))) {
|
||||
SAFE_DELETE(_back);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_IMAGE:
|
||||
SAFE_DELETE(_image);
|
||||
_image = new BaseSprite(_game);
|
||||
if (!_image || DID_FAIL(_image->loadFile(params))) {
|
||||
SAFE_DELETE(_image);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_FONT:
|
||||
if (_font) {
|
||||
_game->_fontStorage->removeFont(_font);
|
||||
}
|
||||
_font = _game->_fontStorage->addFont(params);
|
||||
if (!_font) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_FONT_SELECTED:
|
||||
if (_fontSelected) {
|
||||
_game->_fontStorage->removeFont(_fontSelected);
|
||||
}
|
||||
_fontSelected = _game->_fontStorage->addFont(params);
|
||||
if (!_fontSelected) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_TEXT:
|
||||
setText(params);
|
||||
_game->_stringTable->expand(&_text);
|
||||
break;
|
||||
|
||||
case TOKEN_X:
|
||||
parser.scanStr(params, "%d", &_posX);
|
||||
break;
|
||||
|
||||
case TOKEN_Y:
|
||||
parser.scanStr(params, "%d", &_posY);
|
||||
break;
|
||||
|
||||
case TOKEN_WIDTH:
|
||||
parser.scanStr(params, "%d", &_width);
|
||||
break;
|
||||
|
||||
case TOKEN_HEIGHT:
|
||||
parser.scanStr(params, "%d", &_height);
|
||||
break;
|
||||
|
||||
case TOKEN_MAX_LENGTH:
|
||||
parser.scanStr(params, "%d", &_maxLength);
|
||||
break;
|
||||
|
||||
case TOKEN_CAPTION:
|
||||
setCaption(params);
|
||||
break;
|
||||
|
||||
case TOKEN_CURSOR:
|
||||
SAFE_DELETE(_cursor);
|
||||
_cursor = new BaseSprite(_game);
|
||||
if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
|
||||
SAFE_DELETE(_cursor);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_CURSOR_BLINK_RATE:
|
||||
parser.scanStr(params, "%d", &_cursorBlinkRate);
|
||||
break;
|
||||
|
||||
case TOKEN_FRAME_WIDTH:
|
||||
parser.scanStr(params, "%d", &_frameWidth);
|
||||
break;
|
||||
|
||||
case TOKEN_SCRIPT:
|
||||
addScript(params);
|
||||
break;
|
||||
|
||||
case TOKEN_PARENT_NOTIFY:
|
||||
parser.scanStr(params, "%b", &_parentNotify);
|
||||
break;
|
||||
|
||||
case TOKEN_DISABLED:
|
||||
parser.scanStr(params, "%b", &_disable);
|
||||
break;
|
||||
|
||||
case TOKEN_VISIBLE:
|
||||
parser.scanStr(params, "%b", &_visible);
|
||||
break;
|
||||
|
||||
case TOKEN_EDITOR_PROPERTY:
|
||||
parseEditorProperty(params, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd == PARSERR_TOKENNOTFOUND) {
|
||||
_game->LOG(0, "Syntax error in EDIT definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
if (cmd == PARSERR_GENERIC) {
|
||||
_game->LOG(0, "Error loading EDIT definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
correctSize();
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::saveAsText(BaseDynamicBuffer *buffer, int indent) {
|
||||
buffer->putTextIndent(indent, "EDIT\n");
|
||||
buffer->putTextIndent(indent, "{\n");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name);
|
||||
buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption());
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
if (_back && _back->_filename && _back->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename);
|
||||
}
|
||||
|
||||
if (_image && _image->_filename && _image->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename);
|
||||
}
|
||||
|
||||
if (_font && _font->_filename && _font->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename);
|
||||
}
|
||||
if (_fontSelected && _fontSelected->_filename && _fontSelected->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "FONT_SELECTED=\"%s\"\n", _fontSelected->_filename);
|
||||
}
|
||||
|
||||
if (_cursor && _cursor->_filename && _cursor->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename);
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
if (_text && _text[0]) {
|
||||
buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text);
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "X=%d\n", _posX);
|
||||
buffer->putTextIndent(indent + 2, "Y=%d\n", _posY);
|
||||
buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width);
|
||||
buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height);
|
||||
buffer->putTextIndent(indent + 2, "MAX_LENGTH=%d\n", _maxLength);
|
||||
buffer->putTextIndent(indent + 2, "CURSOR_BLINK_RATE=%d\n", _cursorBlinkRate);
|
||||
buffer->putTextIndent(indent + 2, "FRAME_WIDTH=%d\n", _frameWidth);
|
||||
|
||||
buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
|
||||
buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
|
||||
buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE");
|
||||
|
||||
// scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
// editor properties
|
||||
BaseClass::saveAsText(buffer, indent + 2);
|
||||
|
||||
buffer->putTextIndent(indent, "}\n");
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// high level scripting interface
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetSelectedFont
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SetSelectedFont") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
if (_fontSelected) {
|
||||
_game->_fontStorage->removeFont(_fontSelected);
|
||||
}
|
||||
_fontSelected = _game->_fontStorage->addFont(stack->pop()->getString());
|
||||
stack->pushBool(_fontSelected != nullptr);
|
||||
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return UIObject::scCallMethod(script, stack, thisStack, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *UIEdit::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("editor");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SelStart
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SelStart") == 0) {
|
||||
_scValue->setInt(_selStart);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SelEnd
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SelEnd") == 0) {
|
||||
_scValue->setInt(_selEnd);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CursorBlinkRate
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "CursorBlinkRate") == 0) {
|
||||
_scValue->setInt(_cursorBlinkRate);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CursorChar
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "CursorChar") == 0) {
|
||||
_scValue->setString(_cursorChar);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FrameWidth
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "FrameWidth") == 0) {
|
||||
_scValue->setInt(_frameWidth);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaxLength
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MaxLength") == 0) {
|
||||
_scValue->setInt(_maxLength);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Text
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Text") == 0) {
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
WideString wstr = StringUtil::ansiToWide(_text);
|
||||
_scValue->setString(StringUtil::wideToUtf8(wstr).c_str());
|
||||
} else {
|
||||
_scValue->setString(_text);
|
||||
}
|
||||
return _scValue;
|
||||
} else {
|
||||
return UIObject::scGetProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SelStart
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SelStart") == 0) {
|
||||
_selStart = value->getInt();
|
||||
_selStart = MAX<int32>(_selStart, 0);
|
||||
_selStart = MIN(_selStart, (int32)strlen(_text));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SelEnd
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SelEnd") == 0) {
|
||||
_selEnd = value->getInt();
|
||||
_selEnd = MAX<int32>(_selEnd, 0);
|
||||
_selEnd = MIN(_selEnd, (int32)strlen(_text));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CursorBlinkRate
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "CursorBlinkRate") == 0) {
|
||||
_cursorBlinkRate = (uint32)value->getInt();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CursorChar
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "CursorChar") == 0) {
|
||||
setCursorChar(value->getString());
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FrameWidth
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "FrameWidth") == 0) {
|
||||
_frameWidth = value->getInt();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MaxLength
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MaxLength") == 0) {
|
||||
_maxLength = value->getInt();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Text
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Text") == 0) {
|
||||
if (_game->_textEncoding == TEXT_UTF8) {
|
||||
WideString wstr = StringUtil::utf8ToWide(value->getString());
|
||||
setText(StringUtil::wideToAnsi(wstr).c_str());
|
||||
} else {
|
||||
setText(value->getString());
|
||||
}
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return UIObject::scSetProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *UIEdit::scToString() {
|
||||
return "[edit]";
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void UIEdit::setCursorChar(const char *character) {
|
||||
if (!character) {
|
||||
return;
|
||||
}
|
||||
SAFE_DELETE_ARRAY(_cursorChar);
|
||||
size_t cursorCharSize = strlen(character) + 1;
|
||||
_cursorChar = new char [cursorCharSize];
|
||||
Common::strcpy_s(_cursorChar, cursorCharSize, character);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::display(int offsetX, int offsetY) {
|
||||
if (!_visible) {
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
// hack!
|
||||
TTextEncoding OrigEncoding = _game->_textEncoding;
|
||||
_game->_textEncoding = TEXT_ANSI;
|
||||
|
||||
if (_back) {
|
||||
_back->display(offsetX + _posX, offsetY + _posY, _width, _height);
|
||||
}
|
||||
if (_image) {
|
||||
_image->draw(offsetX + _posX, offsetY + _posY, nullptr);
|
||||
}
|
||||
|
||||
// prepare fonts
|
||||
BaseFont *font;
|
||||
BaseFont *sfont;
|
||||
|
||||
if (_font) {
|
||||
font = _font;
|
||||
} else {
|
||||
font = _game->_systemFont;
|
||||
}
|
||||
|
||||
if (_fontSelected) {
|
||||
sfont = _fontSelected;
|
||||
} else {
|
||||
sfont = font;
|
||||
}
|
||||
|
||||
bool focused = isFocused();
|
||||
|
||||
_selStart = MAX<int32>(_selStart, 0);
|
||||
_selEnd = MAX<int32>(_selEnd, 0);
|
||||
|
||||
_selStart = MIN(_selStart, (int32)strlen(_text));
|
||||
_selEnd = MIN(_selEnd, (int32)strlen(_text));
|
||||
|
||||
//int cursorWidth = font->getCharWidth(_cursorChar[0]);
|
||||
int cursorWidth = font->getTextWidth((byte *)_cursorChar);
|
||||
|
||||
int32 s1, s2;
|
||||
bool curFirst;
|
||||
// modify scroll offset
|
||||
if (_selStart >= _selEnd) {
|
||||
while (font->getTextWidth((byte *)_text + _scrollOffset, MAX<int32>(0, _selEnd - _scrollOffset)) > _width - cursorWidth - 2 * _frameWidth) {
|
||||
_scrollOffset++;
|
||||
if (_scrollOffset >= (int)strlen(_text)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_scrollOffset = MIN(_scrollOffset, _selEnd);
|
||||
|
||||
s1 = _selEnd;
|
||||
s2 = _selStart;
|
||||
curFirst = true;
|
||||
} else {
|
||||
while (font->getTextWidth((byte *)_text + _scrollOffset, MAX<int32>(0, _selStart - _scrollOffset)) +
|
||||
sfont->getTextWidth((byte *)(_text + MAX<int32>(_scrollOffset, _selStart)), _selEnd - MAX(_scrollOffset, _selStart))
|
||||
> _width - cursorWidth - 2 * _frameWidth) {
|
||||
_scrollOffset++;
|
||||
if (_scrollOffset >= (int32)strlen(_text)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_scrollOffset = MIN(_scrollOffset, _selEnd);
|
||||
|
||||
s1 = _selStart;
|
||||
s2 = _selEnd;
|
||||
curFirst = false;
|
||||
}
|
||||
|
||||
|
||||
int alignOffset = 0;
|
||||
|
||||
for (int count = 0; count < 2; count++) {
|
||||
// draw text
|
||||
int xxx, yyy, width, height;
|
||||
|
||||
xxx = _posX + _frameWidth + offsetX;
|
||||
yyy = _posY + _frameWidth + offsetY;
|
||||
|
||||
width = _posX + _width + offsetX - _frameWidth;
|
||||
height = MAX(font->getLetterHeight(), sfont->getLetterHeight());
|
||||
|
||||
if (_game->_textRTL) {
|
||||
xxx += alignOffset;
|
||||
}
|
||||
|
||||
TTextAlign align = TAL_LEFT;
|
||||
|
||||
|
||||
// unselected 1
|
||||
if (s1 > _scrollOffset) {
|
||||
if (count) {
|
||||
font->drawText((byte *)_text + _scrollOffset, xxx, yyy, width - xxx, align, height, s1 - _scrollOffset);
|
||||
}
|
||||
xxx += font->getTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset);
|
||||
alignOffset += font->getTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset);
|
||||
}
|
||||
|
||||
// cursor
|
||||
if (focused && curFirst) {
|
||||
if (count) {
|
||||
if (BasePlatform::getTime() - _lastBlinkTime >= _cursorBlinkRate) {
|
||||
_lastBlinkTime = BasePlatform::getTime();
|
||||
_cursorVisible = !_cursorVisible;
|
||||
}
|
||||
if (_cursorVisible) {
|
||||
font->drawText((byte *)_cursorChar, xxx, yyy, width - xxx, align, height, 1);
|
||||
}
|
||||
}
|
||||
xxx += cursorWidth;
|
||||
alignOffset += cursorWidth;
|
||||
}
|
||||
|
||||
// selected
|
||||
int s3 = MAX(s1, _scrollOffset);
|
||||
|
||||
if (s2 - s3 > 0) {
|
||||
if (count) {
|
||||
sfont->drawText((byte *)_text + s3, xxx, yyy, width - xxx, align, height, s2 - s3);
|
||||
}
|
||||
xxx += sfont->getTextWidth((byte *)_text + s3, s2 - s3);
|
||||
alignOffset += sfont->getTextWidth((byte *)_text + s3, s2 - s3);
|
||||
}
|
||||
|
||||
// cursor
|
||||
if (focused && !curFirst) {
|
||||
if (count) {
|
||||
if (BasePlatform::getTime() - _lastBlinkTime >= _cursorBlinkRate) {
|
||||
_lastBlinkTime = BasePlatform::getTime();
|
||||
_cursorVisible = !_cursorVisible;
|
||||
}
|
||||
if (_cursorVisible) {
|
||||
font->drawText((byte *)_cursorChar, xxx, yyy, width - xxx, align, height, 1);
|
||||
}
|
||||
}
|
||||
xxx += cursorWidth;
|
||||
alignOffset += cursorWidth;
|
||||
}
|
||||
|
||||
// unselected 2
|
||||
if (count) {
|
||||
font->drawText((byte *)_text + s2, xxx, yyy, width - xxx, align, height);
|
||||
}
|
||||
alignOffset += font->getTextWidth((byte *)_text + s2);
|
||||
|
||||
alignOffset = (_width - 2 * _frameWidth) - alignOffset;
|
||||
if (alignOffset < 0) {
|
||||
alignOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_game->_renderer->_rectList.add(new BaseActiveRect(_game, this, nullptr, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false));
|
||||
|
||||
if (_game->_accessMgr->getActiveObject() == this) {
|
||||
Common::Rect32 rc;
|
||||
BasePlatform::setRect(&rc, offsetX + _posX, offsetY + _posY, offsetX + _posX + _width, offsetY + _posY + _height);
|
||||
_game->_accessMgr->setHintRect(&rc, true);
|
||||
}
|
||||
|
||||
_game->_textEncoding = OrigEncoding;
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::handleKeypress(Common::Event *event, bool printable) {
|
||||
if (event->type != Common::EVENT_KEYDOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (event->kbd.keycode) {
|
||||
|
||||
// Those keys are 'printable' in WME 1.x, let's ignore them
|
||||
case Common::KEYCODE_ESCAPE:
|
||||
case Common::KEYCODE_TAB:
|
||||
case Common::KEYCODE_KP_ENTER:
|
||||
case Common::KEYCODE_RETURN:
|
||||
return false;
|
||||
|
||||
// Movement keys are controlling _selEnd and _selStart
|
||||
case Common::KEYCODE_HOME:
|
||||
case Common::KEYCODE_END:
|
||||
case Common::KEYCODE_LEFT:
|
||||
case Common::KEYCODE_UP:
|
||||
case Common::KEYCODE_RIGHT:
|
||||
case Common::KEYCODE_DOWN:
|
||||
if (event->kbd.keycode == Common::KEYCODE_HOME) {
|
||||
_selEnd = _game->_textRTL ? strlen(_text) : 0;
|
||||
} else if (event->kbd.keycode == Common::KEYCODE_END) {
|
||||
_selEnd = _game->_textRTL ? 0 : strlen(_text);
|
||||
} else if (event->kbd.keycode == Common::KEYCODE_LEFT ||
|
||||
event->kbd.keycode == Common::KEYCODE_UP) {
|
||||
_selEnd--;
|
||||
} else {
|
||||
_selEnd++;
|
||||
}
|
||||
|
||||
if (!BaseKeyboardState::isShiftDown()) {
|
||||
_selStart = _selEnd;
|
||||
}
|
||||
return true;
|
||||
|
||||
// Delete right
|
||||
case Common::KEYCODE_DELETE:
|
||||
if (_selStart == _selEnd) {
|
||||
if (_game->_textRTL) {
|
||||
deleteChars(_selStart - 1, _selStart);
|
||||
_selEnd--;
|
||||
if (_selEnd < 0) {
|
||||
_selEnd = 0;
|
||||
}
|
||||
} else {
|
||||
deleteChars(_selStart, _selStart + 1);
|
||||
}
|
||||
} else {
|
||||
deleteChars(_selStart, _selEnd);
|
||||
}
|
||||
if (_selEnd > _selStart) {
|
||||
_selEnd -= (_selEnd - _selStart);
|
||||
}
|
||||
_selStart = _selEnd;
|
||||
return true;
|
||||
|
||||
// Delete left
|
||||
case Common::KEYCODE_BACKSPACE:
|
||||
if (_selStart == _selEnd) {
|
||||
if (_game->_textRTL) {
|
||||
deleteChars(_selStart, _selStart + 1);
|
||||
} else {
|
||||
deleteChars(_selStart - 1, _selStart);
|
||||
}
|
||||
} else {
|
||||
deleteChars(_selStart, _selEnd);
|
||||
}
|
||||
if (_selEnd >= _selStart) {
|
||||
_selEnd -= MAX<int32>(1, _selEnd - _selStart);
|
||||
}
|
||||
_selStart = _selEnd;
|
||||
return true;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Ctrl+A = Select All
|
||||
if (BaseKeyboardState::isControlDown() && event->kbd.keycode == Common::KEYCODE_a) {
|
||||
_selStart = 0;
|
||||
_selEnd = strlen(_text);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Those are actually printable characters
|
||||
else if (printable) {
|
||||
if (_selStart != _selEnd) {
|
||||
deleteChars(_selStart, _selEnd);
|
||||
}
|
||||
|
||||
//WideString wstr = StringUtil::Utf8ToWide(event->kbd.ascii);
|
||||
WideString wstr;
|
||||
wstr += (char)event->kbd.ascii;
|
||||
_selEnd += insertChars(_selEnd, (const byte *)StringUtil::wideToAnsi(wstr).c_str(), 1);
|
||||
|
||||
if (_game->_textRTL) {
|
||||
_selEnd = _selStart;
|
||||
} else {
|
||||
_selStart = _selEnd;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int UIEdit::deleteChars(int start, int end) {
|
||||
if (start > end) {
|
||||
BaseUtils::swap(&start, &end);
|
||||
}
|
||||
|
||||
start = MAX(start, (int)0);
|
||||
end = MIN(end, (int)strlen(_text));
|
||||
|
||||
char *str = new char[strlen(_text) - (end - start) + 1];
|
||||
if (str) {
|
||||
if (start > 0) {
|
||||
memcpy(str, _text, start);
|
||||
}
|
||||
memcpy(str + MAX(0, start), _text + end, strlen(_text) - end + 1);
|
||||
|
||||
SAFE_DELETE_ARRAY(_text);
|
||||
_text = str;
|
||||
}
|
||||
if (_parentNotify && _parent) {
|
||||
_parent->applyEvent(_name);
|
||||
}
|
||||
|
||||
return end - start;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int UIEdit::insertChars(int pos, const byte *chars, int num) {
|
||||
if ((_maxLength != -1) && (int)strlen(_text) + num > _maxLength) {
|
||||
num -= (strlen(_text) + num - _maxLength);
|
||||
}
|
||||
|
||||
pos = MAX(pos, (int)0);
|
||||
pos = MIN(pos, (int)strlen(_text));
|
||||
|
||||
char *str = new char[strlen(_text) + num + 1];
|
||||
if (str) {
|
||||
if (pos > 0) {
|
||||
memcpy(str, _text, pos);
|
||||
}
|
||||
memcpy(str + pos + num, _text + pos, strlen(_text) - pos + 1);
|
||||
|
||||
memcpy(str + pos, chars, num);
|
||||
|
||||
SAFE_DELETE_ARRAY(_text);
|
||||
_text = str;
|
||||
}
|
||||
if (_parentNotify && _parent) {
|
||||
_parent->applyEvent(_name);
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEdit::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
UIObject::persist(persistMgr);
|
||||
|
||||
persistMgr->transferUint32(TMEMBER(_cursorBlinkRate));
|
||||
persistMgr->transferCharPtr(TMEMBER(_cursorChar));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_fontSelected));
|
||||
persistMgr->transferSint32(TMEMBER(_frameWidth));
|
||||
persistMgr->transferSint32(TMEMBER(_maxLength));
|
||||
persistMgr->transferSint32(TMEMBER(_scrollOffset));
|
||||
persistMgr->transferSint32(TMEMBER(_selEnd));
|
||||
persistMgr->transferSint32(TMEMBER(_selStart));
|
||||
|
||||
if (!persistMgr->getIsSaving()) {
|
||||
_cursorVisible = false;
|
||||
_lastBlinkTime = 0;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
71
engines/wintermute/ui/ui_edit.h
Normal file
71
engines/wintermute/ui/ui_edit.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/persistent.h"
|
||||
#include "engines/wintermute/ui/ui_object.h"
|
||||
#include "common/events.h"
|
||||
|
||||
namespace Wintermute {
|
||||
class BaseFont;
|
||||
class UIEdit : public UIObject {
|
||||
public:
|
||||
DECLARE_PERSISTENT(UIEdit, UIObject)
|
||||
int32 _maxLength;
|
||||
int insertChars(int pos, const byte *chars, int num);
|
||||
int deleteChars(int start, int end);
|
||||
bool _cursorVisible;
|
||||
uint32 _lastBlinkTime;
|
||||
bool display(int offsetX, int offsetY) override;
|
||||
bool handleKeypress(Common::Event *event, bool printable = false) override;
|
||||
int32 _scrollOffset;
|
||||
int32 _frameWidth;
|
||||
uint32 _cursorBlinkRate;
|
||||
void setCursorChar(const char *character);
|
||||
char *_cursorChar;
|
||||
int32 _selEnd;
|
||||
int32 _selStart;
|
||||
BaseFont *_fontSelected;
|
||||
UIEdit(BaseGame *inGame);
|
||||
~UIEdit() override;
|
||||
|
||||
bool loadFile(const char *filename);
|
||||
bool loadBuffer(char *buffer, bool complete = true);
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
// scripting interface
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
368
engines/wintermute/ui/ui_entity.cpp
Normal file
368
engines/wintermute/ui/ui_entity.cpp
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/ad/ad_entity.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/ui/ui_entity.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/base_dynamic_buffer.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(UIEntity, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIEntity::UIEntity(BaseGame *inGame) : UIObject(inGame) {
|
||||
_type = UI_CUSTOM;
|
||||
_entity = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIEntity::~UIEntity() {
|
||||
if (_entity) {
|
||||
_game->unregisterObject(_entity);
|
||||
}
|
||||
_entity = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::loadFile(const char *filename) {
|
||||
char *buffer = (char *)_game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
_game->LOG(0, "UIEntity::loadFile failed for file '%s'", filename);
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
|
||||
setFilename(filename);
|
||||
|
||||
if (DID_FAIL(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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::loadBuffer(char *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
|
||||
|
||||
char *params;
|
||||
int cmd = 2;
|
||||
BaseParser parser(_game);
|
||||
|
||||
if (complete) {
|
||||
if (parser.getCommand(&buffer, commands, ¶ms) != TOKEN_ENTITY_CONTAINER) {
|
||||
_game->LOG(0, "'ENTITY_CONTAINER' keyword expected.");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
buffer = params;
|
||||
}
|
||||
|
||||
while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
switch (cmd) {
|
||||
case TOKEN_TEMPLATE:
|
||||
if (DID_FAIL(loadFile(params))) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_NAME:
|
||||
setName(params);
|
||||
break;
|
||||
|
||||
case TOKEN_X:
|
||||
parser.scanStr(params, "%d", &_posX);
|
||||
break;
|
||||
|
||||
case TOKEN_Y:
|
||||
parser.scanStr(params, "%d", &_posY);
|
||||
break;
|
||||
|
||||
case TOKEN_DISABLED:
|
||||
parser.scanStr(params, "%b", &_disable);
|
||||
break;
|
||||
|
||||
case TOKEN_VISIBLE:
|
||||
parser.scanStr(params, "%b", &_visible);
|
||||
break;
|
||||
|
||||
case TOKEN_ENTITY:
|
||||
if (DID_FAIL(setEntity(params))) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_SCRIPT:
|
||||
addScript(params);
|
||||
break;
|
||||
|
||||
case TOKEN_EDITOR_PROPERTY:
|
||||
parseEditorProperty(params, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd == PARSERR_TOKENNOTFOUND) {
|
||||
_game->LOG(0, "Syntax error in ENTITY_CONTAINER definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
if (cmd == PARSERR_GENERIC) {
|
||||
_game->LOG(0, "Error loading ENTITY_CONTAINER definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
correctSize();
|
||||
|
||||
if (_game->_editorMode) {
|
||||
_width = 50;
|
||||
_height = 50;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) {
|
||||
buffer->putTextIndent(indent, "ENTITY_CONTAINER\n");
|
||||
buffer->putTextIndent(indent, "{\n");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name);
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "X=%d\n", _posX);
|
||||
buffer->putTextIndent(indent + 2, "Y=%d\n", _posY);
|
||||
|
||||
buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
|
||||
buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
|
||||
|
||||
if (_entity && _entity->_filename && _entity->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "ENTITY=\"%s\"\n", _entity->_filename);
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
// scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
// editor properties
|
||||
BaseClass::saveAsText(buffer, indent + 2);
|
||||
|
||||
buffer->putTextIndent(indent, "}\n");
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::setEntity(const char *filename) {
|
||||
if (_entity) {
|
||||
_game->unregisterObject(_entity);
|
||||
}
|
||||
_entity = new AdEntity(_game);
|
||||
if (!_entity || DID_FAIL(_entity->loadFile(filename))) {
|
||||
SAFE_DELETE(_entity);
|
||||
return STATUS_FAILED;
|
||||
} else {
|
||||
_entity->_nonIntMouseEvents = true;
|
||||
_entity->_sceneIndependent = true;
|
||||
_entity->makeFreezable(false);
|
||||
_game->registerObject(_entity);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::display(int offsetX, int offsetY) {
|
||||
if (!_visible) {
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
if (_entity) {
|
||||
_entity->_posX = offsetX + _posX;
|
||||
_entity->_posY = offsetY + _posY;
|
||||
if (_entity->_scale < 0) {
|
||||
_entity->_zoomable = false;
|
||||
}
|
||||
_entity->_shadowable = false;
|
||||
|
||||
_entity->update();
|
||||
|
||||
bool origReg = _entity->_registrable;
|
||||
|
||||
if (_entity->_registrable && _disable) {
|
||||
_entity->_registrable = false;
|
||||
}
|
||||
|
||||
_entity->display();
|
||||
_entity->_registrable = origReg;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// high level scripting interface
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetEntity
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "GetEntity") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
if (_entity) {
|
||||
stack->pushNative(_entity, true);
|
||||
} else {
|
||||
stack->pushNULL();
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetEntity
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetEntity") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
const char *filename = stack->pop()->getString();
|
||||
|
||||
if (DID_SUCCEED(setEntity(filename))) {
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return UIObject::scCallMethod(script, stack, thisStack, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *UIEntity::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("entity container");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Freezable
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Freezable") == 0) {
|
||||
if (_entity) {
|
||||
_scValue->setBool(_entity->_freezable);
|
||||
} else {
|
||||
_scValue->setBool(false);
|
||||
}
|
||||
return _scValue;
|
||||
} else {
|
||||
return UIObject::scGetProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Freezable
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Freezable") == 0) {
|
||||
if (_entity) {
|
||||
_entity->makeFreezable(value->getBool());
|
||||
}
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return UIObject::scSetProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *UIEntity::scToString() {
|
||||
return "[entity container]";
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIEntity::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
UIObject::persist(persistMgr);
|
||||
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_entity));
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
58
engines/wintermute/ui/ui_entity.h
Normal file
58
engines/wintermute/ui/ui_entity.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/ui/ui_object.h"
|
||||
|
||||
namespace Wintermute {
|
||||
class AdEntity;
|
||||
class UIEntity : public UIObject {
|
||||
public:
|
||||
DECLARE_PERSISTENT(UIEntity, UIObject)
|
||||
UIEntity(BaseGame *inGame);
|
||||
~UIEntity() override;
|
||||
bool loadFile(const char *filename);
|
||||
bool loadBuffer(char *buffer, bool complete);
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
bool display() override { return display(0, 0); }
|
||||
bool display(int offsetX, int offsetY) override;
|
||||
AdEntity *_entity;
|
||||
bool setEntity(const char *filename);
|
||||
|
||||
// scripting interface
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
658
engines/wintermute/ui/ui_object.cpp
Normal file
658
engines/wintermute/ui/ui_object.cpp
Normal file
@@ -0,0 +1,658 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_sprite.h"
|
||||
#include "engines/wintermute/ui/ui_object.h"
|
||||
#include "engines/wintermute/ui/ui_tiled_image.h"
|
||||
#include "engines/wintermute/ui/ui_window.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/base/gfx/base_renderer.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/font/base_font_storage.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(UIObject, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIObject::UIObject(BaseGame *inGame) : BaseObject(inGame) {
|
||||
_back = nullptr;
|
||||
_image = nullptr;
|
||||
_font = nullptr;
|
||||
_text = nullptr;
|
||||
_sharedFonts = _sharedImages = false;
|
||||
|
||||
_width = _height = 0;
|
||||
|
||||
_listenerObject = nullptr;
|
||||
_listenerParamObject = nullptr;
|
||||
_listenerParamDWORD = 0;
|
||||
|
||||
_disable = false;
|
||||
_visible = true;
|
||||
|
||||
_type = UI_UNKNOWN;
|
||||
_parent = nullptr;
|
||||
|
||||
_parentNotify = false;
|
||||
|
||||
_focusedWidget = nullptr;
|
||||
|
||||
_canFocus = false;
|
||||
_nonIntMouseEvents = true;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIObject::~UIObject() {
|
||||
if (!_game->_loadInProgress) {
|
||||
SystemClassRegistry::getInstance()->enumInstances(BaseGame::invalidateValues, "ScValue", (void *)this);
|
||||
}
|
||||
|
||||
if (_back) {
|
||||
delete _back;
|
||||
}
|
||||
if (_font && !_sharedFonts) {
|
||||
_game->_fontStorage->removeFont(_font);
|
||||
}
|
||||
|
||||
if (_image && !_sharedImages) {
|
||||
delete _image;
|
||||
}
|
||||
|
||||
if (_text) {
|
||||
delete[] _text;
|
||||
}
|
||||
|
||||
_focusedWidget = nullptr; // ref only
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void UIObject::setText(const char *text) {
|
||||
if (_text) {
|
||||
delete[] _text;
|
||||
}
|
||||
size_t textSize = strlen(text) + 1;
|
||||
_text = new char [textSize];
|
||||
Common::strcpy_s(_text, textSize, text);
|
||||
for (uint32 i = 0; i < strlen(_text); i++) {
|
||||
if (_text[i] == '|') {
|
||||
_text[i] = '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::display(int offsetX, int offsetY) {
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void UIObject::setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam) {
|
||||
_listenerObject = object;
|
||||
_listenerParamObject = listenerObject;
|
||||
_listenerParamDWORD = listenerParam;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void UIObject::correctSize() {
|
||||
Common::Rect32 rect;
|
||||
|
||||
if (_width <= 0) {
|
||||
if (_image) {
|
||||
_image->getBoundingRect(&rect, 0, 0);
|
||||
_width = rect.right - rect.left;
|
||||
} else {
|
||||
_width = 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (_height <= 0) {
|
||||
if (_image) {
|
||||
_image->getBoundingRect(&rect, 0, 0);
|
||||
_height = rect.bottom - rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
if (_back) {
|
||||
_back->correctSize(&_width, &_height);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// high level scripting interface
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetFont
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SetFont") == 0) {
|
||||
stack->correctParams(1);
|
||||
ScValue *val = stack->pop();
|
||||
|
||||
if (_font) {
|
||||
_game->_fontStorage->removeFont(_font);
|
||||
}
|
||||
if (val->isNULL()) {
|
||||
_font = nullptr;
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
_font = _game->_fontStorage->addFont(val->getString());
|
||||
stack->pushBool(_font != nullptr);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SetImage
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "SetImage") == 0) {
|
||||
stack->correctParams(1);
|
||||
ScValue *val = stack->pop();
|
||||
|
||||
/* const char *filename = */ val->getString();
|
||||
|
||||
SAFE_DELETE(_image);
|
||||
if (val->isNULL()) {
|
||||
stack->pushBool(true);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
_image = new BaseSprite(_game);
|
||||
if (!_image || DID_FAIL(_image->loadFile(val->getString()))) {
|
||||
SAFE_DELETE(_image);
|
||||
stack->pushBool(false);
|
||||
} else {
|
||||
stack->pushBool(true);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetImage
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetImage") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (!_image || !_image->_filename || !_image->_filename[0]) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushString(_image->_filename);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// GetImageObject
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "GetImageObject") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (!_image) {
|
||||
stack->pushNULL();
|
||||
} else {
|
||||
stack->pushNative(_image, true);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Focus
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Focus") == 0) {
|
||||
stack->correctParams(0);
|
||||
focus();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MoveAfter / MoveBefore
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MoveAfter") == 0 || strcmp(name, "MoveBefore") == 0) {
|
||||
stack->correctParams(1);
|
||||
|
||||
if (_parent && _parent->_type == UI_WINDOW) {
|
||||
UIWindow *win = (UIWindow *)_parent;
|
||||
|
||||
int32 i;
|
||||
bool found = false;
|
||||
ScValue *val = stack->pop();
|
||||
// find directly
|
||||
if (val->isNative()) {
|
||||
UIObject *widget = (UIObject *)val->getNative();
|
||||
for (i = 0; i < win->_widgets.getSize(); i++) {
|
||||
if (win->_widgets[i] == widget) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// find by name
|
||||
else {
|
||||
const char *findName = val->getString();
|
||||
for (i = 0; i < win->_widgets.getSize(); i++) {
|
||||
if (scumm_stricmp(win->_widgets[i]->_name, findName) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
bool done = false;
|
||||
for (int32 j = 0; j < win->_widgets.getSize(); j++) {
|
||||
if (win->_widgets[j] == this) {
|
||||
if (strcmp(name, "MoveAfter") == 0) {
|
||||
i++;
|
||||
}
|
||||
if (j >= i) {
|
||||
j++;
|
||||
}
|
||||
|
||||
win->_widgets.insertAt(i, this);
|
||||
win->_widgets.removeAt(j);
|
||||
|
||||
done = true;
|
||||
stack->pushBool(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MoveToBottom
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MoveToBottom") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
if (_parent && _parent->_type == UI_WINDOW) {
|
||||
UIWindow *win = (UIWindow *)_parent;
|
||||
for (int32 i = 0; i < win->_widgets.getSize(); i++) {
|
||||
if (win->_widgets[i] == this) {
|
||||
win->_widgets.removeAt(i);
|
||||
win->_widgets.insertAt(0, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MoveToTop
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "MoveToTop") == 0) {
|
||||
stack->correctParams(0);
|
||||
|
||||
if (_parent && _parent->_type == UI_WINDOW) {
|
||||
UIWindow *win = (UIWindow *)_parent;
|
||||
for (int32 i = 0; i < win->_widgets.getSize(); i++) {
|
||||
if (win->_widgets[i] == this) {
|
||||
win->_widgets.removeAt(i);
|
||||
win->_widgets.add(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
stack->pushBool(true);
|
||||
} else {
|
||||
stack->pushBool(false);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return BaseObject::scCallMethod(script, stack, thisStack, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *UIObject::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("ui_object");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Name") == 0) {
|
||||
_scValue->setString(_name);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Parent (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Parent") == 0) {
|
||||
_scValue->setNative(_parent, true);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ParentNotify
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ParentNotify") == 0) {
|
||||
_scValue->setBool(_parentNotify);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Width
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Width") == 0) {
|
||||
_scValue->setInt(_width);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Height
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Height") == 0) {
|
||||
_scValue->setInt(_height);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Visible
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Visible") == 0) {
|
||||
_scValue->setBool(_visible);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Disabled
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Disabled") == 0) {
|
||||
_scValue->setBool(_disable);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Text
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Text") == 0) {
|
||||
_scValue->setString(_text);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// NextSibling (RO) / PrevSibling (RO)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "NextSibling") == 0 || strcmp(name, "PrevSibling") == 0) {
|
||||
_scValue->setNULL();
|
||||
if (_parent && _parent->_type == UI_WINDOW) {
|
||||
UIWindow *win = (UIWindow *)_parent;
|
||||
for (int32 i = 0; i < win->_widgets.getSize(); i++) {
|
||||
if (win->_widgets[i] == this) {
|
||||
if (strcmp(name, "NextSibling") == 0) {
|
||||
if (i < win->_widgets.getSize() - 1) {
|
||||
_scValue->setNative(win->_widgets[i + 1], true);
|
||||
}
|
||||
} else {
|
||||
if (i > 0) {
|
||||
_scValue->setNative(win->_widgets[i - 1], true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _scValue;
|
||||
} else {
|
||||
return BaseObject::scGetProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Name
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Name") == 0) {
|
||||
setName(value->getString());
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ParentNotify
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "ParentNotify") == 0) {
|
||||
_parentNotify = value->getBool();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Width
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Width") == 0) {
|
||||
_width = value->getInt();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Height
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Height") == 0) {
|
||||
_height = value->getInt();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Visible
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Visible") == 0) {
|
||||
_visible = value->getBool();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Disabled
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Disabled") == 0) {
|
||||
_disable = value->getBool();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Text
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "Text") == 0) {
|
||||
setText(value->getString());
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return BaseObject::scSetProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *UIObject::scToString() {
|
||||
return "[ui_object]";
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::isFocused() {
|
||||
if (!_game->_focusedWindow) {
|
||||
return false;
|
||||
}
|
||||
if (_game->_focusedWindow == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
UIObject *obj = _game->_focusedWindow;
|
||||
while (obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
} else {
|
||||
obj = obj->_focusedWidget;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::handleMouse(TMouseEvent event, TMouseButton button) {
|
||||
// handle focus change
|
||||
if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) {
|
||||
focus();
|
||||
}
|
||||
return BaseObject::handleMouse(event, button);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::focus() {
|
||||
UIObject *obj = this;
|
||||
bool disabled = false;
|
||||
while (obj) {
|
||||
if (obj->_disable && obj->_type == UI_WINDOW) {
|
||||
disabled = true;
|
||||
break;
|
||||
}
|
||||
obj = obj->_parent;
|
||||
}
|
||||
if (!disabled) {
|
||||
obj = this;
|
||||
while (obj) {
|
||||
if (obj->_parent) {
|
||||
if (!obj->_disable && obj->_canFocus) {
|
||||
obj->_parent->_focusedWidget = obj;
|
||||
}
|
||||
} else {
|
||||
if (obj->_type == UI_WINDOW) {
|
||||
_game->focusWindow((UIWindow *)obj);
|
||||
}
|
||||
}
|
||||
|
||||
obj = obj->_parent;
|
||||
}
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::getTotalOffset(int *offsetX, int *offsetY) {
|
||||
int offX = 0, offY = 0;
|
||||
|
||||
UIObject *obj = _parent;
|
||||
while (obj) {
|
||||
offX += obj->_posX;
|
||||
offY += obj->_posY;
|
||||
|
||||
obj = obj->_parent;
|
||||
}
|
||||
if (offsetX) {
|
||||
*offsetX = offX;
|
||||
}
|
||||
if (offsetY) {
|
||||
*offsetY = offY;
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
BaseObject::persist(persistMgr);
|
||||
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_back));
|
||||
persistMgr->transferBool(TMEMBER(_canFocus));
|
||||
persistMgr->transferBool(TMEMBER(_disable));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_focusedWidget));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_font));
|
||||
persistMgr->transferSint32(TMEMBER(_height));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_image));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_listenerObject));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_listenerParamObject));
|
||||
persistMgr->transferUint32(TMEMBER(_listenerParamDWORD));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_parent));
|
||||
persistMgr->transferBool(TMEMBER(_parentNotify));
|
||||
persistMgr->transferBool(TMEMBER(_sharedFonts));
|
||||
persistMgr->transferBool(TMEMBER(_sharedImages));
|
||||
persistMgr->transferCharPtr(TMEMBER(_text));
|
||||
persistMgr->transferSint32(TMEMBER_INT(_type));
|
||||
persistMgr->transferBool(TMEMBER(_visible));
|
||||
persistMgr->transferSint32(TMEMBER(_width));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *UIObject::getAccessCaption() {
|
||||
if (_accessCaption)
|
||||
return _accessCaption;
|
||||
else {
|
||||
if (_text && _text[0])
|
||||
return _text;
|
||||
else
|
||||
return getCaption();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIObject::saveAsText(BaseDynamicBuffer *buffer, int indent) {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
85
engines/wintermute/ui/ui_object.h
Normal file
85
engines/wintermute/ui/ui_object.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/base/base_object.h"
|
||||
#include "engines/wintermute/dctypes.h" // Added by ClassView
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class UITiledImage;
|
||||
class BaseFont;
|
||||
class UIObject : public BaseObject {
|
||||
public:
|
||||
const char *getAccessCaption() override;
|
||||
|
||||
bool getTotalOffset(int *offsetX, int *offsetY);
|
||||
bool _canFocus;
|
||||
bool focus();
|
||||
bool handleMouse(TMouseEvent event, TMouseButton button) override;
|
||||
bool isFocused();
|
||||
bool _parentNotify;
|
||||
DECLARE_PERSISTENT(UIObject, BaseObject)
|
||||
UIObject *_parent;
|
||||
bool display() override { return display(0, 0); }
|
||||
virtual bool display(int offsetX) { return display(offsetX, 0); }
|
||||
virtual bool display(int offsetX, int offsetY);
|
||||
virtual void correctSize();
|
||||
bool _sharedFonts;
|
||||
bool _sharedImages;
|
||||
void setText(const char *text);
|
||||
char *_text;
|
||||
BaseFont *_font;
|
||||
bool _visible;
|
||||
UITiledImage *_back;
|
||||
bool _disable;
|
||||
UIObject(BaseGame *inGame = nullptr);
|
||||
~UIObject() override;
|
||||
int32 _width;
|
||||
int32 _height;
|
||||
TUIObjectType _type;
|
||||
BaseSprite *_image;
|
||||
void setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam);
|
||||
BaseScriptHolder *_listenerParamObject;
|
||||
uint32 _listenerParamDWORD;
|
||||
BaseScriptHolder *_listenerObject;
|
||||
UIObject *_focusedWidget;
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
// scripting interface
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
521
engines/wintermute/ui/ui_text.cpp
Normal file
521
engines/wintermute/ui/ui_text.cpp
Normal file
@@ -0,0 +1,521 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/base/base_dynamic_buffer.h"
|
||||
#include "engines/wintermute/ui/ui_text.h"
|
||||
#include "engines/wintermute/ui/ui_tiled_image.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/scriptables/script_value.h"
|
||||
#include "engines/wintermute/base/font/base_font.h"
|
||||
#include "engines/wintermute/base/font/base_font_storage.h"
|
||||
#include "engines/wintermute/base/base_string_table.h"
|
||||
#include "engines/wintermute/base/scriptables/script.h"
|
||||
#include "engines/wintermute/base/scriptables/script_stack.h"
|
||||
#include "engines/wintermute/base/base_sprite.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(UIText, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIText::UIText(BaseGame *inGame) : UIObject(inGame) {
|
||||
_textAlign = TAL_LEFT;
|
||||
_verticalAlign = VAL_CENTER;
|
||||
_type = UI_STATIC;
|
||||
_canFocus = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UIText::~UIText() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::display(int offsetX, int offsetY) {
|
||||
if (!_visible) {
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
BaseFont *font = _font;
|
||||
if (!font) {
|
||||
font = _game->_systemFont;
|
||||
}
|
||||
|
||||
if (_back) {
|
||||
_back->display(offsetX + _posX, offsetY + _posY, _width, _height);
|
||||
}
|
||||
if (_image) {
|
||||
_image->draw(offsetX + _posX, offsetY + _posY, nullptr);
|
||||
}
|
||||
|
||||
if (font && _text && _text[0]) {
|
||||
int textOffset;
|
||||
switch (_verticalAlign) {
|
||||
case VAL_TOP:
|
||||
textOffset = 0;
|
||||
break;
|
||||
case VAL_BOTTOM:
|
||||
textOffset = _height - font->getTextHeight((byte *)_text, _width);
|
||||
break;
|
||||
default:
|
||||
textOffset = (_height - font->getTextHeight((byte *)_text, _width)) / 2;
|
||||
}
|
||||
font->drawText((byte *)_text, offsetX + _posX, offsetY + _posY + textOffset, _width, _textAlign, _height);
|
||||
}
|
||||
|
||||
//_game->_renderer->_rectList.add(new BaseActiveRect(_game, this, nullptr, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::loadFile(const char *filename) {
|
||||
char *buffer = (char *) _game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
_game->LOG(0, "UIText::loadFile failed for file '%s'", filename);
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
|
||||
setFilename(filename);
|
||||
|
||||
if (DID_FAIL(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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::loadBuffer(char *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
|
||||
|
||||
char *params;
|
||||
int cmd = 2;
|
||||
BaseParser parser(_game);
|
||||
|
||||
if (complete) {
|
||||
if (parser.getCommand(&buffer, commands, ¶ms) != TOKEN_STATIC) {
|
||||
_game->LOG(0, "'STATIC' keyword expected.");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
buffer = params;
|
||||
}
|
||||
|
||||
while (cmd > 0 && (cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
switch (cmd) {
|
||||
case TOKEN_TEMPLATE:
|
||||
if (DID_FAIL(loadFile(params))) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_NAME:
|
||||
setName(params);
|
||||
break;
|
||||
|
||||
case TOKEN_CAPTION:
|
||||
setCaption(params);
|
||||
break;
|
||||
|
||||
case TOKEN_BACK:
|
||||
SAFE_DELETE(_back);
|
||||
_back = new UITiledImage(_game);
|
||||
if (!_back || DID_FAIL(_back->loadFile(params))) {
|
||||
SAFE_DELETE(_back);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_IMAGE:
|
||||
SAFE_DELETE(_image);
|
||||
_image = new BaseSprite(_game);
|
||||
if (!_image || DID_FAIL(_image->loadFile(params))) {
|
||||
SAFE_DELETE(_image);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_FONT:
|
||||
if (_font) {
|
||||
_game->_fontStorage->removeFont(_font);
|
||||
}
|
||||
_font = _game->_fontStorage->addFont(params);
|
||||
if (!_font) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_TEXT:
|
||||
setText(params);
|
||||
_game->_stringTable->expand(&_text);
|
||||
break;
|
||||
|
||||
case TOKEN_TEXT_ALIGN:
|
||||
if (scumm_stricmp(params, "left") == 0) {
|
||||
_textAlign = TAL_LEFT;
|
||||
} else if (scumm_stricmp(params, "right") == 0) {
|
||||
_textAlign = TAL_RIGHT;
|
||||
} else {
|
||||
_textAlign = TAL_CENTER;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_VERTICAL_ALIGN:
|
||||
if (scumm_stricmp(params, "top") == 0) {
|
||||
_verticalAlign = VAL_TOP;
|
||||
} else if (scumm_stricmp(params, "bottom") == 0) {
|
||||
_verticalAlign = VAL_BOTTOM;
|
||||
} else {
|
||||
_verticalAlign = VAL_CENTER;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_X:
|
||||
parser.scanStr(params, "%d", &_posX);
|
||||
break;
|
||||
|
||||
case TOKEN_Y:
|
||||
parser.scanStr(params, "%d", &_posY);
|
||||
break;
|
||||
|
||||
case TOKEN_WIDTH:
|
||||
parser.scanStr(params, "%d", &_width);
|
||||
break;
|
||||
|
||||
case TOKEN_HEIGHT:
|
||||
parser.scanStr(params, "%d", &_height);
|
||||
break;
|
||||
|
||||
case TOKEN_CURSOR:
|
||||
SAFE_DELETE(_cursor);
|
||||
_cursor = new BaseSprite(_game);
|
||||
if (!_cursor || DID_FAIL(_cursor->loadFile(params))) {
|
||||
SAFE_DELETE(_cursor);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_SCRIPT:
|
||||
addScript(params);
|
||||
break;
|
||||
|
||||
case TOKEN_PARENT_NOTIFY:
|
||||
parser.scanStr(params, "%b", &_parentNotify);
|
||||
break;
|
||||
|
||||
case TOKEN_DISABLED:
|
||||
parser.scanStr(params, "%b", &_disable);
|
||||
break;
|
||||
|
||||
case TOKEN_VISIBLE:
|
||||
parser.scanStr(params, "%b", &_visible);
|
||||
break;
|
||||
|
||||
case TOKEN_EDITOR_PROPERTY:
|
||||
parseEditorProperty(params, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd == PARSERR_TOKENNOTFOUND) {
|
||||
_game->LOG(0, "Syntax error in STATIC definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
if (cmd == PARSERR_GENERIC) {
|
||||
_game->LOG(0, "Error loading STATIC definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
correctSize();
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::saveAsText(BaseDynamicBuffer *buffer, int indent) {
|
||||
buffer->putTextIndent(indent, "STATIC\n");
|
||||
buffer->putTextIndent(indent, "{\n");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _name);
|
||||
buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption());
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
if (_back && _back->_filename && _back->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->_filename);
|
||||
}
|
||||
|
||||
if (_image && _image->_filename && _image->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_filename);
|
||||
}
|
||||
|
||||
if (_font && _font->_filename && _font->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->_filename);
|
||||
}
|
||||
|
||||
if (_cursor && _cursor->_filename && _cursor->_filename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename);
|
||||
}
|
||||
|
||||
if (_text && _text[0]) {
|
||||
buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text);
|
||||
}
|
||||
|
||||
switch (_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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "X=%d\n", _posX);
|
||||
buffer->putTextIndent(indent + 2, "Y=%d\n", _posY);
|
||||
buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width);
|
||||
buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height);
|
||||
|
||||
buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
|
||||
buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
|
||||
buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE");
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
// scripts
|
||||
for (int32 i = 0; i < _scripts.getSize(); i++) {
|
||||
buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
|
||||
}
|
||||
|
||||
buffer->putTextIndent(indent + 2, "\n");
|
||||
|
||||
// editor properties
|
||||
BaseClass::saveAsText(buffer, indent + 2);
|
||||
|
||||
buffer->putTextIndent(indent, "}\n");
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// high level scripting interface
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SizeToFit
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "SizeToFit") == 0) {
|
||||
stack->correctParams(0);
|
||||
sizeToFit();
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HeightToFit
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "HeightToFit") == 0) {
|
||||
stack->correctParams(0);
|
||||
if (_font && _text) {
|
||||
_height = _font->getTextHeight((byte *)_text, _width);
|
||||
}
|
||||
stack->pushNULL();
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return UIObject::scCallMethod(script, stack, thisStack, name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
ScValue *UIText::scGetProperty(const char *name) {
|
||||
_scValue->setNULL();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "Type") == 0) {
|
||||
_scValue->setString("static");
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TextAlign
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "TextAlign") == 0) {
|
||||
_scValue->setInt(_textAlign);
|
||||
return _scValue;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VerticalAlign
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "VerticalAlign") == 0) {
|
||||
_scValue->setInt(_verticalAlign);
|
||||
return _scValue;
|
||||
} else {
|
||||
return UIObject::scGetProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::scSetProperty(const char *name, ScValue *value) {
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TextAlign
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (strcmp(name, "TextAlign") == 0) {
|
||||
int i = value->getInt();
|
||||
if (i < 0 || i >= NUM_TEXT_ALIGN) {
|
||||
i = 0;
|
||||
}
|
||||
_textAlign = (TTextAlign)i;
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VerticalAlign
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
else if (strcmp(name, "VerticalAlign") == 0) {
|
||||
int i = value->getInt();
|
||||
if (i < 0 || i >= NUM_VERTICAL_ALIGN) {
|
||||
i = 0;
|
||||
}
|
||||
_verticalAlign = (TVerticalAlign)i;
|
||||
return STATUS_OK;
|
||||
} else {
|
||||
return UIObject::scSetProperty(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const char *UIText::scToString() {
|
||||
return "[static]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::persist(BasePersistenceManager *persistMgr) {
|
||||
|
||||
UIObject::persist(persistMgr);
|
||||
persistMgr->transferSint32(TMEMBER_INT(_textAlign));
|
||||
persistMgr->transferSint32(TMEMBER_INT(_verticalAlign));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UIText::sizeToFit() {
|
||||
if (_font && _text && _text[0]) {
|
||||
_width = _font->getTextWidth((byte *)_text);
|
||||
_height = _font->getTextHeight((byte *)_text, _width);
|
||||
}
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
58
engines/wintermute/ui/ui_text.h
Normal file
58
engines/wintermute/ui/ui_text.h
Normal file
@@ -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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/ui/ui_object.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class UIText : public UIObject {
|
||||
public:
|
||||
bool sizeToFit();
|
||||
bool display(int offsetX, int offsetY) override;
|
||||
DECLARE_PERSISTENT(UIText, UIObject)
|
||||
UIText(BaseGame *inGame = nullptr);
|
||||
~UIText() override;
|
||||
TTextAlign _textAlign;
|
||||
TVerticalAlign _verticalAlign;
|
||||
bool loadFile(const char *filename);
|
||||
bool loadBuffer(char *buffer, bool complete = true);
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
// scripting interface
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
387
engines/wintermute/ui/ui_tiled_image.cpp
Normal file
387
engines/wintermute/ui/ui_tiled_image.cpp
Normal file
@@ -0,0 +1,387 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/ui/ui_tiled_image.h"
|
||||
#include "engines/wintermute/base/gfx/base_surface.h"
|
||||
#include "engines/wintermute/base/base_dynamic_buffer.h"
|
||||
#include "engines/wintermute/base/base_parser.h"
|
||||
#include "engines/wintermute/base/base_game.h"
|
||||
#include "engines/wintermute/base/base_sub_frame.h"
|
||||
#include "engines/wintermute/base/base_file_manager.h"
|
||||
#include "engines/wintermute/base/gfx/base_renderer.h"
|
||||
#include "engines/wintermute/platform_osystem.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
IMPLEMENT_PERSISTENT(UITiledImage, false)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UITiledImage::UITiledImage(BaseGame *inGame) : BaseObject(inGame) {
|
||||
_image = nullptr;
|
||||
|
||||
BasePlatform::setRectEmpty(&_upLeft);
|
||||
BasePlatform::setRectEmpty(&_upMiddle);
|
||||
BasePlatform::setRectEmpty(&_upRight);
|
||||
BasePlatform::setRectEmpty(&_middleLeft);
|
||||
BasePlatform::setRectEmpty(&_middleMiddle);
|
||||
BasePlatform::setRectEmpty(&_middleRight);
|
||||
BasePlatform::setRectEmpty(&_downLeft);
|
||||
BasePlatform::setRectEmpty(&_downMiddle);
|
||||
BasePlatform::setRectEmpty(&_downRight);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
UITiledImage::~UITiledImage() {
|
||||
SAFE_DELETE(_image);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UITiledImage::display(int x, int y, int width, int height) {
|
||||
if (!_image) {
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
int tileWidth = _middleMiddle.right - _middleMiddle.left;
|
||||
int tileHeight = _middleMiddle.bottom - _middleMiddle.top;
|
||||
|
||||
int numColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth;
|
||||
int numRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight;
|
||||
|
||||
_game->_renderer->startSpriteBatch();
|
||||
|
||||
// top left/right
|
||||
_image->_surface->displayTrans(x, y, _upLeft);
|
||||
_image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + numColumns * tileWidth, y, _upRight);
|
||||
|
||||
// bottom left/right
|
||||
_image->_surface->displayTrans(x, y + (_upMiddle.bottom - _upMiddle.top) + numRows * tileHeight, _downLeft);
|
||||
_image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + numColumns * tileWidth, y + (_upMiddle.bottom - _upMiddle.top) + numRows * tileHeight, _downRight);
|
||||
|
||||
// left/right
|
||||
if (numRows > 0) {
|
||||
int yyy = y + (_upMiddle.bottom - _upMiddle.top);
|
||||
_image->_surface->displayTiled(x, yyy, _middleLeft, 1, numRows);
|
||||
_image->_surface->displayTiled(x + (_middleLeft.right - _middleLeft.left) + numColumns * tileWidth, yyy, _middleRight, 1, numRows);
|
||||
}
|
||||
|
||||
// top/bottom
|
||||
if (numColumns > 0) {
|
||||
int xxx = x + (_upLeft.right - _upLeft.left);
|
||||
_image->_surface->displayTiled(xxx, y, _upMiddle, numColumns, 1);
|
||||
_image->_surface->displayTiled(xxx, y + (_upMiddle.bottom - _upMiddle.top) + numRows * tileHeight, _downMiddle, numColumns, 1);
|
||||
}
|
||||
|
||||
// tiles
|
||||
if (numRows > 0 && numColumns > 0) {
|
||||
int yyy = y + (_upMiddle.bottom - _upMiddle.top);
|
||||
int xxx = x + (_upLeft.right - _upLeft.left);
|
||||
_image->_surface->displayTiled(xxx, yyy, _middleMiddle, numColumns, numRows);
|
||||
}
|
||||
|
||||
_game->_renderer->endSpriteBatch();
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UITiledImage::loadFile(const char *filename) {
|
||||
char *buffer = (char *)_game->_fileManager->readWholeFile(filename);
|
||||
if (buffer == nullptr) {
|
||||
_game->LOG(0, "UITiledImage::loadFile failed for file '%s'", filename);
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
bool ret;
|
||||
|
||||
setFilename(filename);
|
||||
|
||||
if (DID_FAIL(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
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UITiledImage::loadBuffer(char *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
|
||||
|
||||
char *params;
|
||||
int cmd;
|
||||
BaseParser 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(&buffer, commands, ¶ms) != TOKEN_TILED_IMAGE) {
|
||||
_game->LOG(0, "'TILED_IMAGE' keyword expected.");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
buffer = params;
|
||||
}
|
||||
|
||||
while ((cmd = parser.getCommand(&buffer, commands, ¶ms)) > 0) {
|
||||
switch (cmd) {
|
||||
case TOKEN_TEMPLATE:
|
||||
if (DID_FAIL(loadFile(params))) {
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_IMAGE:
|
||||
SAFE_DELETE(_image);
|
||||
_image = new BaseSubFrame(_game);
|
||||
if (!_image || DID_FAIL(_image->setSurface(params))) {
|
||||
SAFE_DELETE(_image);
|
||||
cmd = PARSERR_GENERIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOKEN_UP_LEFT:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_upLeft.left, &_upLeft.top, &_upLeft.right, &_upLeft.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_UP_RIGHT:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_upRight.left, &_upRight.top, &_upRight.right, &_upRight.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_UP_MIDDLE:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_upMiddle.left, &_upMiddle.top, &_upMiddle.right, &_upMiddle.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_DOWN_LEFT:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_downLeft.left, &_downLeft.top, &_downLeft.right, &_downLeft.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_DOWN_RIGHT:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_downRight.left, &_downRight.top, &_downRight.right, &_downRight.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_DOWN_MIDDLE:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_downMiddle.left, &_downMiddle.top, &_downMiddle.right, &_downMiddle.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_MIDDLE_LEFT:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_middleLeft.left, &_middleLeft.top, &_middleLeft.right, &_middleLeft.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_MIDDLE_RIGHT:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_middleRight.left, &_middleRight.top, &_middleRight.right, &_middleRight.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_MIDDLE_MIDDLE:
|
||||
parser.scanStr(params, "%d,%d,%d,%d", &_middleMiddle.left, &_middleMiddle.top, &_middleMiddle.right, &_middleMiddle.bottom);
|
||||
break;
|
||||
|
||||
case TOKEN_HORIZONTAL_TILES:
|
||||
parser.scanStr(params, "%d,%d,%d", &h1, &h2, &h3);
|
||||
hTiles = true;
|
||||
break;
|
||||
|
||||
case TOKEN_VERTICAL_TILES:
|
||||
parser.scanStr(params, "%d,%d,%d", &v1, &v2, &v3);
|
||||
vTiles = true;
|
||||
break;
|
||||
|
||||
case TOKEN_EDITOR_PROPERTY:
|
||||
parseEditorProperty(params, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd == PARSERR_TOKENNOTFOUND) {
|
||||
_game->LOG(0, "Syntax error in TILED_IMAGE definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
if (cmd == PARSERR_GENERIC) {
|
||||
_game->LOG(0, "Error loading TILED_IMAGE definition");
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
if (vTiles && hTiles) {
|
||||
// up row
|
||||
BasePlatform::setRect(&_upLeft, 0, 0, h1, v1);
|
||||
BasePlatform::setRect(&_upMiddle, h1, 0, h1 + h2, v1);
|
||||
BasePlatform::setRect(&_upRight, h1 + h2, 0, h1 + h2 + h3, v1);
|
||||
|
||||
// middle row
|
||||
BasePlatform::setRect(&_middleLeft, 0, v1, h1, v1 + v2);
|
||||
BasePlatform::setRect(&_middleMiddle, h1, v1, h1 + h2, v1 + v2);
|
||||
BasePlatform::setRect(&_middleRight, h1 + h2, v1, h1 + h2 + h3, v1 + v2);
|
||||
|
||||
// down row
|
||||
BasePlatform::setRect(&_downLeft, 0, v1 + v2, h1, v1 + v2 + v3);
|
||||
BasePlatform::setRect(&_downMiddle, h1, v1 + v2, h1 + h2, v1 + v2 + v3);
|
||||
BasePlatform::setRect(&_downRight, h1 + h2, v1 + v2, h1 + h2 + h3, v1 + v2 + v3);
|
||||
}
|
||||
|
||||
// default
|
||||
if (_image && _image->_surface) {
|
||||
int width = _image->_surface->getWidth() / 3;
|
||||
int height = _image->_surface->getHeight() / 3;
|
||||
|
||||
if (BasePlatform::isRectEmpty(&_upLeft)) {
|
||||
BasePlatform::setRect(&_upLeft, 0, 0, width, height);
|
||||
}
|
||||
if (BasePlatform::isRectEmpty(&_upMiddle)) {
|
||||
BasePlatform::setRect(&_upMiddle, width, 0, 2 * width, height);
|
||||
}
|
||||
if (BasePlatform::isRectEmpty(&_upRight)) {
|
||||
BasePlatform::setRect(&_upRight, 2 * width, 0, 3 * width, height);
|
||||
}
|
||||
|
||||
if (BasePlatform::isRectEmpty(&_middleLeft)) {
|
||||
BasePlatform::setRect(&_middleLeft, 0, height, width, 2 * height);
|
||||
}
|
||||
if (BasePlatform::isRectEmpty(&_middleMiddle)) {
|
||||
BasePlatform::setRect(&_middleMiddle, width, height, 2 * width, 2 * height);
|
||||
}
|
||||
if (BasePlatform::isRectEmpty(&_middleRight)) {
|
||||
BasePlatform::setRect(&_middleRight, 2 * width, height, 3 * width, 2 * height);
|
||||
}
|
||||
|
||||
if (BasePlatform::isRectEmpty(&_downLeft)) {
|
||||
BasePlatform::setRect(&_downLeft, 0, 2 * height, width, 3 * height);
|
||||
}
|
||||
if (BasePlatform::isRectEmpty(&_downMiddle)) {
|
||||
BasePlatform::setRect(&_downMiddle, width, 2 * height, 2 * width, 3 * height);
|
||||
}
|
||||
if (BasePlatform::isRectEmpty(&_downRight)) {
|
||||
BasePlatform::setRect(&_downRight, 2 * width, 2 * height, 3 * width, 3 * height);
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UITiledImage::saveAsText(BaseDynamicBuffer *buffer, int indent) {
|
||||
buffer->putTextIndent(indent, "TILED_IMAGE\n");
|
||||
buffer->putTextIndent(indent, "{\n");
|
||||
|
||||
if (_image && _image->_surfaceFilename && _image->_surfaceFilename[0]) {
|
||||
buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_surfaceFilename);
|
||||
}
|
||||
|
||||
int h1, h2, h3;
|
||||
int v1, v2, v3;
|
||||
|
||||
h1 = _upLeft.right;
|
||||
h2 = _upMiddle.right - _upMiddle.left;
|
||||
h3 = _upRight.right - _upRight.left;
|
||||
|
||||
v1 = _upLeft.bottom;
|
||||
v2 = _middleLeft.bottom - _middleLeft.top;
|
||||
v3 = _downLeft.bottom - _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
|
||||
BaseClass::saveAsText(buffer, indent + 2);
|
||||
|
||||
buffer->putTextIndent(indent, "}\n");
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void UITiledImage::correctSize(int32 *width, int32 *height) {
|
||||
int tileWidth = _middleMiddle.right - _middleMiddle.left;
|
||||
int tileHeight = _middleMiddle.bottom - _middleMiddle.top;
|
||||
|
||||
int numColumns = (*width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth;
|
||||
int numRows = (*height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight;
|
||||
|
||||
*width = (_middleLeft.right - _middleLeft.left) + (_middleRight.right - _middleRight.left) + numColumns * tileWidth;
|
||||
*height = (_upMiddle.bottom - _upMiddle.top) + (_downMiddle.bottom - _downMiddle.top) + numRows * tileHeight;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool UITiledImage::persist(BasePersistenceManager *persistMgr) {
|
||||
BaseObject::persist(persistMgr);
|
||||
|
||||
persistMgr->transferRect32(TMEMBER(_downLeft));
|
||||
persistMgr->transferRect32(TMEMBER(_downMiddle));
|
||||
persistMgr->transferRect32(TMEMBER(_downRight));
|
||||
persistMgr->transferPtr(TMEMBER_PTR(_image));
|
||||
persistMgr->transferRect32(TMEMBER(_middleLeft));
|
||||
persistMgr->transferRect32(TMEMBER(_middleMiddle));
|
||||
persistMgr->transferRect32(TMEMBER(_middleRight));
|
||||
persistMgr->transferRect32(TMEMBER(_upLeft));
|
||||
persistMgr->transferRect32(TMEMBER(_upMiddle));
|
||||
persistMgr->transferRect32(TMEMBER(_upRight));
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
64
engines/wintermute/ui/ui_tiled_image.h
Normal file
64
engines/wintermute/ui/ui_tiled_image.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/ui/ui_object.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Wintermute {
|
||||
class BaseSubFrame;
|
||||
class UITiledImage : public BaseObject {
|
||||
using Wintermute::BaseObject::display;
|
||||
|
||||
public:
|
||||
DECLARE_PERSISTENT(UITiledImage, BaseObject)
|
||||
void correctSize(int32 *width, int32 *height);
|
||||
bool loadFile(const char *filename);
|
||||
bool loadBuffer(char *buffer, bool complete = true);
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
bool display(int x, int y, int width, int height);
|
||||
UITiledImage(BaseGame *inGame = nullptr);
|
||||
~UITiledImage() override;
|
||||
BaseSubFrame *_image;
|
||||
Common::Rect32 _upLeft;
|
||||
Common::Rect32 _upMiddle;
|
||||
Common::Rect32 _upRight;
|
||||
Common::Rect32 _middleLeft;
|
||||
Common::Rect32 _middleMiddle;
|
||||
Common::Rect32 _middleRight;
|
||||
Common::Rect32 _downLeft;
|
||||
Common::Rect32 _downMiddle;
|
||||
Common::Rect32 _downRight;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
1481
engines/wintermute/ui/ui_window.cpp
Normal file
1481
engines/wintermute/ui/ui_window.cpp
Normal file
File diff suppressed because it is too large
Load Diff
94
engines/wintermute/ui/ui_window.h
Normal file
94
engines/wintermute/ui/ui_window.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "engines/wintermute/ui/ui_object.h"
|
||||
#include "common/events.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class UIButton;
|
||||
class BaseViewport;
|
||||
class UIWindow : public UIObject {
|
||||
public:
|
||||
BaseObject *getPrevAccessObject(BaseObject *currObject);
|
||||
BaseObject *getNextAccessObject(BaseObject *currObject);
|
||||
bool getWindowObjects(BaseArray<UIObject *> &objects, bool interactiveOnly);
|
||||
|
||||
bool _pauseMusic;
|
||||
void cleanup();
|
||||
void makeFreezable(bool freezable) override;
|
||||
BaseViewport *_viewport;
|
||||
bool _clipContents;
|
||||
bool _inGame;
|
||||
bool _isMenu;
|
||||
bool _fadeBackground;
|
||||
uint32 _fadeColor;
|
||||
bool handleMouseWheel(int32 delta) override;
|
||||
UIWindow *_shieldWindow;
|
||||
UIButton *_shieldButton;
|
||||
bool close();
|
||||
bool goSystemExclusive();
|
||||
bool goExclusive();
|
||||
TWindowMode _mode;
|
||||
bool moveFocus(bool forward = true);
|
||||
bool handleMouse(TMouseEvent event, TMouseButton button) override;
|
||||
Common::Point32 _dragFrom;
|
||||
bool _dragging;
|
||||
DECLARE_PERSISTENT(UIWindow, UIObject)
|
||||
bool _transparent;
|
||||
bool showWidget(const char *name, bool visible = true);
|
||||
bool enableWidget(const char *name, bool enable = true);
|
||||
Common::Rect32 _titleRect;
|
||||
Common::Rect32 _dragRect;
|
||||
bool display(int offsetX = 0, int offsetY = 0) override;
|
||||
UIWindow(BaseGame *inGame);
|
||||
~UIWindow() override;
|
||||
bool handleKeypress(Common::Event *event, bool printable = false) override;
|
||||
BaseArray<UIObject *> _widgets;
|
||||
TTextAlign _titleAlign;
|
||||
bool loadFile(const char *filename);
|
||||
bool loadBuffer(char *buffer, bool complete = true);
|
||||
UITiledImage *_backInactive;
|
||||
BaseFont *_fontInactive;
|
||||
BaseSprite *_imageInactive;
|
||||
bool listen(BaseScriptHolder *param1, uint32 param2) override;
|
||||
bool saveAsText(BaseDynamicBuffer *buffer, int indent) override;
|
||||
|
||||
// scripting interface
|
||||
ScValue *scGetProperty(const char *name) override;
|
||||
bool scSetProperty(const char *name, ScValue *value) override;
|
||||
bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) override;
|
||||
const char *scToString() override;
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user