add modulemanager module

This commit is contained in:
Eduardo Bart 2012-02-05 23:44:47 -02:00
parent a55e138002
commit 64c9e4f1d5
25 changed files with 379 additions and 60 deletions

3
TODO
View File

@ -75,6 +75,8 @@ game/graphics window with options
do lua game event calls from Game instead from GameProtocol
auto walk
minimap window
login queue
questlog
edit texts
@ -82,4 +84,3 @@ trade window
shop window
battle window
hotkeys window
minimap window

View File

@ -1,6 +1,17 @@
function dumpWidgets()
for i=1,rootWidget:getChildCount() do
print(rootWidget:getChildByIndex(i):getId())
function dumpWidgets(widget, level)
widget = widget or rootWidget
level = level or 0
for i=1,widget:getChildCount() do
local child = widget:getChildByIndex(i)
if child:isVisible() then
local name = child:getId()
if name:match('widget%d+') == nil then
print(string.rep(' ', level) .. name)
end
if child:getId() ~= 'terminalBuffer' then
dumpWidgets(child, level+1)
end
end
end
end

View File

@ -12,6 +12,7 @@ Module
- client_about
- client_options
- client_entergame
- client_modulemanager
- game
onLoad: |

View File

@ -0,0 +1,118 @@
ModuleManager = {}
local moduleManagerWindow
local moduleManagerButton
local moduleList
function ModuleManager.init()
moduleManagerWindow = displayUI('modulemanager.otui')
moduleManagerWindow:hide()
moduleList = moduleManagerWindow:getChildById('moduleList')
connect(moduleList, { onChildFocusChange = function(self, focusedChild)
if focusedChild == nil then return end
ModuleManager.updateModuleInfo(focusedChild:getText())
end })
moduleManagerButton = TopMenu.addButton('moduleManagerButton', 'Module manager', 'modulemanager.png', ModuleManager.toggle)
addEvent(ModuleManager.listModules)
end
function ModuleManager.terminate()
moduleManagerWindow:destroy()
moduleManagerWindow = nil
moduleManagerButton:destroy()
moduleManagerButton = nil
moduleList = nil
end
function ModuleManager.hide()
moduleManagerWindow:hide()
end
function ModuleManager.show()
moduleManagerWindow:show()
moduleManagerWindow:focus()
moduleManagerWindow:raise()
end
function ModuleManager.toggle()
if moduleManagerWindow:isVisible() then
ModuleManager.hide()
else
ModuleManager.show()
end
end
function ModuleManager.refreshModules()
g_modules.discoverModules()
ModuleManager.listModules()
end
function ModuleManager.listModules()
moduleList:destroyChildren()
local modules = g_modules.getModules()
for i,module in ipairs(modules) do
local label = createWidget('ModuleListLabel', moduleList)
label:setText(module:getName())
end
moduleList:focusChild(moduleList:getFirstChild(), ActiveFocusReason)
end
function ModuleManager.updateModuleInfo(moduleName)
local name = ''
local description = ''
local autoLoad = ''
local author = ''
local website = ''
local version = ''
local canLoad = false
local canUnload = false
local module = g_modules.getModule(moduleName)
if module then
name = module:getName()
description = module:getDescription()
author = module:getAuthor()
website = module:getWebsite()
version = module:getVersion()
canUnload = module:isLoaded()
canLoad = not canUnload
end
moduleManagerWindow:recursiveGetChildById('moduleName'):setText(name)
moduleManagerWindow:recursiveGetChildById('moduleDescription'):setText(description)
moduleManagerWindow:recursiveGetChildById('moduleDescription'):wrapText()
moduleManagerWindow:recursiveGetChildById('moduleAuthor'):setText(author)
moduleManagerWindow:recursiveGetChildById('moduleWebsite'):setText(website)
moduleManagerWindow:recursiveGetChildById('moduleVersion'):setText(version)
moduleManagerWindow:recursiveGetChildById('moduleLoadButton'):setEnabled(canLoad)
moduleManagerWindow:recursiveGetChildById('moduleUnloadButton'):setEnabled(canUnload)
end
function ModuleManager.loadCurrentModule()
local focusedChild = moduleList:getFocusedChild()
if focusedChild then
local module = g_modules.getModule(focusedChild:getText())
if module then
module:load()
ModuleManager.updateModuleInfo(module:getName())
end
end
end
function ModuleManager.unloadCurrentModule()
local focusedChild = moduleList:getFocusedChild()
if focusedChild then
local module = g_modules.getModule(focusedChild:getText())
if module then
module:unload()
ModuleManager.updateModuleInfo(module:getName())
end
end
end

View File

@ -0,0 +1,11 @@
Module
name: client_modulemanager
description: Manage other modules
author: OTClient team
website: https://github.com/edubart/otclient
onLoad: |
require 'modulemanager'
ModuleManager.init()
onUnload: |
ModuleManager.terminate()

View File

@ -0,0 +1,117 @@
ModuleListLabel < Label
font: verdana-11px-monochrome
background-color: alpha
text-offset: 2 0
focusable: true
$focus:
background-color: #ffffff22
color: #ffffff
ModuleInfoLabel < Label
$!first:
margin-top: 5
margin-bottom: 2
ModuleValueLabel < UILabel
font: verdana-11px-antialised
color: #aaaaaa
text-offset: 3 0
image-source: /core_styles/images/panel_flat.png
image-border: 1
MainWindow
id: moduleManagerWindow
size: 450 450
text: Module Manager
@onEscape: ModuleManager.hide()
TextList
id: moduleList
anchors.top: parent.top
anchors.left: parent.left
anchors.bottom: parent.bottom
width: 180
padding: 1
focusable: false
margin-bottom: 30
Button
anchors.top: moduleList.bottom
anchors.horizontalCenter: moduleList.horizontalCenter
margin-top: 8
text: Refresh
@onClick: ModuleManager.refreshModules()
Panel
id: moduleInfo
anchors.left: moduleList.right
anchors.top: parent.top
anchors.right: parent.right
margin: 0 5 5 15
layout:
type: verticalBox
fit-children: true
ModuleInfoLabel
text: Module name
ModuleValueLabel
id: moduleName
ModuleInfoLabel
text: Description
ModuleValueLabel
id: moduleDescription
height: 100
ModuleInfoLabel
text: Loaded
ModuleValueLabel
id: moduleLoaded
//ModuleInfoLabel
// text: Autoload
//ModuleValueLabel
// id: moduleAutoload
//ModuleInfoLabel
// text: Autoload antecedence
//ModuleValueLabel
// id: moduleLoadAntecedence
// text: 1000
ModuleInfoLabel
text: Author
ModuleValueLabel
id: moduleAuthor
ModuleInfoLabel
text: Website
ModuleValueLabel
id: moduleWebsite
ModuleInfoLabel
text: Version
ModuleValueLabel
id: moduleVersion
Button
id: moduleLoadButton
anchors.top: moduleInfo.bottom
anchors.left: moduleInfo.left
margin-top: 8
text: Load
enabled: false
@onClick: ModuleManager.loadCurrentModule()
Button
id: moduleUnloadButton
anchors.top: moduleInfo.bottom
anchors.right: moduleInfo.right
margin-left: 10
margin-top: 8
text: Unload
enabled: false
@onClick: ModuleManager.unloadCurrentModule()

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

View File

@ -6,7 +6,7 @@ TopButton < UIButton
image-color: #ffffffff
icon-color: #ffffffff
$hover:
$hover !disabled:
image-color: #ffffff99
image-clip: 26 0 26 26

View File

@ -7,7 +7,7 @@ Button < UIButton
image-source: /core_styles/images/button.png
image-border: 5
$hover:
$hover !disabled:
image-source: /core_styles/images/button_hover.png
$pressed:

View File

@ -8,7 +8,7 @@ CheckBox < UICheckBox
image-offset: 0 2
image-source: /core_styles/images/checkbox.png
$hover:
$hover !disabled:
color: #cccccc
$!checked:
@ -48,7 +48,7 @@ ButtonBox < UICheckBox
image-color: white
image-border: 5
$hover:
$hover !disabled:
image-source: /core_styles/images/button_hover.png
$checked:

View File

@ -6,7 +6,7 @@ ComboBoxPopupMenuButton < UIButton
color: #aaaaaa
background-color: alpha
$hover:
$hover !disabled:
color: #ffffff
background-color: #ffffff44
@ -38,7 +38,7 @@ ComboBox < UIComboBox
image-border-right: 17
image-clip: 0 0 89 20
$hover:
$hover !disabled:
image-clip: 0 20 89 20
$on:

View File

@ -7,7 +7,7 @@ PopupMenuButton < UIButton
color: #aaaaaa
background-color: alpha
$hover:
$hover !disabled:
color: #ffffff
background-color: #ffffff44

View File

@ -1,5 +1,5 @@
Module
name: game_minewindow
name: game_miniwindow
description: Manage game miniwindow
author: OTClient team
website: https://github.com/edubart/otclient

View File

@ -162,8 +162,6 @@ void Application::terminate()
void Application::run()
{
g_lua.callGlobalField("g_app", "onRun");
ticks_t lastPollTicks = g_clock.updateTicks();
m_stopping = false;
m_running = true;

View File

@ -221,7 +221,7 @@ namespace Fw
enum FocusReason {
MouseFocusReason = 0,
TabFocusReason,
KeyboardFocusReason,
ActiveFocusReason,
OtherFocusReason
};

View File

@ -25,6 +25,7 @@
#include <framework/global.h>
class ModuleManager;
class Module;
class Event;
class ScheduledEvent;

View File

@ -31,36 +31,6 @@ Module::Module(const std::string& name)
m_name = name;
}
void Module::discover(const OTMLNodePtr& moduleNode)
{
const static std::string none = "none";
m_description = moduleNode->valueAt("description", none);
m_author = moduleNode->valueAt("author", none);
m_website = moduleNode->valueAt("website", none);
m_version = moduleNode->valueAt("version", none);
m_autoLoad = moduleNode->valueAt<bool>("autoLoad", false);
m_autoLoadAntecedence = moduleNode->valueAt<int>("autoLoadAntecedence", 100);
if(OTMLNodePtr node = moduleNode->get("dependencies")) {
for(const OTMLNodePtr& tmp : node->children())
m_dependencies.push_back(tmp->value());
}
// set onLoad callback
if(OTMLNodePtr node = moduleNode->get("onLoad")) {
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
g_lua.useValue();
m_loadCallback = g_lua.polymorphicPop<SimpleCallback>();
}
// set onUnload callback
if(OTMLNodePtr node = moduleNode->get("onUnload")) {
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
g_lua.useValue();
m_unloadCallback = g_lua.polymorphicPop<SimpleCallback>();
}
}
bool Module::load()
{
if(m_loaded)
@ -95,3 +65,34 @@ void Module::unload()
m_loaded = false;
}
}
void Module::discover(const OTMLNodePtr& moduleNode)
{
const static std::string none = "none";
m_description = moduleNode->valueAt("description", none);
m_author = moduleNode->valueAt("author", none);
m_website = moduleNode->valueAt("website", none);
m_version = moduleNode->valueAt("version", none);
m_autoLoad = moduleNode->valueAt<bool>("autoLoad", false);
m_autoLoadAntecedence = moduleNode->valueAt<int>("autoLoadAntecedence", 100);
if(OTMLNodePtr node = moduleNode->get("dependencies")) {
for(const OTMLNodePtr& tmp : node->children())
m_dependencies.push_back(tmp->value());
}
// set onLoad callback
if(OTMLNodePtr node = moduleNode->get("onLoad")) {
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
g_lua.useValue();
m_loadCallback = g_lua.polymorphicPop<SimpleCallback>();
}
// set onUnload callback
if(OTMLNodePtr node = moduleNode->get("onUnload")) {
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
g_lua.useValue();
m_unloadCallback = g_lua.polymorphicPop<SimpleCallback>();
}
}

View File

@ -26,12 +26,12 @@
#include "declarations.h"
#include <framework/otml/declarations.h>
#include <framework/luascript/luaobject.h>
class Module
class Module : public LuaObject
{
public:
Module(const std::string& name);
void discover(const OTMLNodePtr& moduleNode);
bool load();
void unload();
@ -46,6 +46,10 @@ public:
bool isAutoLoad() { return m_autoLoad; }
int getAutoLoadAntecedence() { return m_autoLoadAntecedence; }
protected:
void discover(const OTMLNodePtr& moduleNode);
friend class ModuleManager;
private:
Boolean<false> m_loaded;
Boolean<false> m_autoLoad;

View File

@ -30,6 +30,9 @@ ModuleManager g_modules;
void ModuleManager::discoverModules()
{
// remove modules that are not loaded
m_autoLoadModules.clear();
auto moduleDirs = g_resources.listDirectoryFiles("/");
for(const std::string& moduleDir : moduleDirs) {
auto moduleFiles = g_resources.listDirectoryFiles("/" + moduleDir);
@ -85,12 +88,19 @@ ModulePtr ModuleManager::discoverModule(const std::string& moduleFile)
OTMLNodePtr moduleNode = doc->at("Module");
std::string name = moduleNode->valueAt("name");
if(getModule(name))
Fw::throwException("module '", name, "' already exists, cannot have duplicate module names");
//if(getModule(name))
// Fw::throwException("module '", name, "' already exists, cannot have duplicate module names");
module = ModulePtr(new Module(name));
bool push = false;
module = getModule(name);
if(!module) {
module = ModulePtr(new Module(name));
push = true;
}
module->discover(moduleNode);
m_modules.push_back(module);
if(push)
m_modules.push_back(module);
} catch(Exception& e) {
logError("Unable to discover module from file '", moduleFile, "': ", e.what());
}

View File

@ -36,6 +36,7 @@ public:
void unloadModules();
ModulePtr getModule(const std::string& moduleName);
std::vector<ModulePtr> getModules() { return m_modules; }
private:
std::vector<ModulePtr> m_modules;

View File

@ -30,6 +30,8 @@
#include <framework/otml/otml.h>
#include <framework/graphics/graphics.h>
#include <framework/platform/platformwindow.h>
#include <framework/core/modulemanager.h>
#include <framework/core/module.h>
void Application::registerLuaFunctions()
{
@ -83,6 +85,7 @@ void Application::registerLuaFunctions()
g_lua.bindClassMemberFunction<UIWidget>("ungrabKeyboard", &UIWidget::ungrabKeyboard);
g_lua.bindClassMemberFunction<UIWidget>("bindRectToParent", &UIWidget::bindRectToParent);
g_lua.bindClassMemberFunction<UIWidget>("destroy", &UIWidget::destroy);
g_lua.bindClassMemberFunction<UIWidget>("destroyChildren", &UIWidget::destroyChildren);
g_lua.bindClassMemberFunction<UIWidget>("setId", &UIWidget::setId);
g_lua.bindClassMemberFunction<UIWidget>("setParent", &UIWidget::setParent);
g_lua.bindClassMemberFunction<UIWidget>("setLayout", &UIWidget::setLayout);
@ -361,6 +364,19 @@ void Application::registerLuaFunctions()
// Protocol
g_lua.registerClass<Protocol>();
// Module
g_lua.registerClass<Module>();
g_lua.bindClassMemberFunction<Module>("load", &Module::load);
g_lua.bindClassMemberFunction<Module>("unload", &Module::unload);
g_lua.bindClassMemberFunction<Module>("isLoaded", &Module::isLoaded);
g_lua.bindClassMemberFunction<Module>("getDescription", &Module::getDescription);
g_lua.bindClassMemberFunction<Module>("getName", &Module::getName);
g_lua.bindClassMemberFunction<Module>("getAuthor", &Module::getAuthor);
g_lua.bindClassMemberFunction<Module>("getWebsite", &Module::getWebsite);
g_lua.bindClassMemberFunction<Module>("getVersion", &Module::getVersion);
g_lua.bindClassMemberFunction<Module>("isAutoLoad", &Module::isAutoLoad);
g_lua.bindClassMemberFunction<Module>("getAutoLoadAntecedence", &Module::getAutoLoadAntecedence);
// network manipulation via lua is disabled for a while
/*
// OutputMessage
@ -451,6 +467,17 @@ void Application::registerLuaFunctions()
g_lua.bindClassStaticFunction("g_ui", "setDebugBoxesDrawing", std::bind(&UIManager::setDebugBoxesDrawing, &g_ui, _1));
g_lua.bindClassStaticFunction("g_ui", "isDrawingDebugBoxes", std::bind(&UIManager::setDebugBoxesDrawing, &g_ui, _1));
// ModuleManager
g_lua.registerStaticClass("g_modules");
g_lua.bindClassStaticFunction("g_modules", "discoverModulesPath", std::bind(&ModuleManager::discoverModulesPath, &g_modules));
g_lua.bindClassStaticFunction("g_modules", "discoverModules", std::bind(&ModuleManager::discoverModules, &g_modules));
g_lua.bindClassStaticFunction("g_modules", "autoLoadModules", std::bind(&ModuleManager::autoLoadModules, &g_modules, _1));
g_lua.bindClassStaticFunction("g_modules", "discoverModule", std::bind(&ModuleManager::discoverModule, &g_modules, _1));
g_lua.bindClassStaticFunction("g_modules", "ensureModuleLoaded", std::bind(&ModuleManager::ensureModuleLoaded, &g_modules, _1));
g_lua.bindClassStaticFunction("g_modules", "unloadModules", std::bind(&ModuleManager::unloadModules, &g_modules));
g_lua.bindClassStaticFunction("g_modules", "getModule", std::bind(&ModuleManager::getModule, &g_modules, _1));
g_lua.bindClassStaticFunction("g_modules", "getModules", std::bind(&ModuleManager::getModules, &g_modules));
// FontManager
g_lua.registerStaticClass("g_fonts");
g_lua.bindClassStaticFunction("g_fonts", "importFont", std::bind(&FontManager::importFont, &g_fonts, _1));

View File

@ -421,7 +421,7 @@ void UILineEdit::onGeometryChange(const Rect& oldRect, const Rect& newRect)
void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason)
{
if(focused && !m_alwaysActive) {
if(reason == Fw::TabFocusReason)
if(reason == Fw::KeyboardFocusReason)
setCursorPos(m_text.length());
else
blinkCursor();
@ -452,7 +452,7 @@ bool UILineEdit::onKeyPress(uchar keyCode, int keyboardModifiers, bool wouldFilt
else if(keyCode == Fw::KeyTab) {
if(!m_alwaysActive) {
if(UIWidgetPtr parent = getParent())
parent->focusNextChild(Fw::TabFocusReason);
parent->focusNextChild(Fw::KeyboardFocusReason);
}
} else
return false;

View File

@ -219,6 +219,8 @@ void UIWidget::focusChild(const UIWidgetPtr& child, Fw::FocusReason reason)
oldFocused->updateState(Fw::FocusState);
oldFocused->updateState(Fw::ActiveState);
}
onChildFocusChange(child, oldFocused, reason);
}
void UIWidget::focusNextChild(Fw::FocusReason reason)
@ -485,7 +487,6 @@ void UIWidget::lower()
void UIWidget::raise()
{
focus();
UIWidgetPtr parent = getParent();
if(parent)
parent->raiseChild(asUIWidget());
@ -546,9 +547,7 @@ void UIWidget::destroy()
parent->removeChild(asUIWidget());
}
// destroy children
while(!m_children.empty())
getFirstChild()->destroy();
destroyChildren();
callLuaField("onDestroy");
@ -568,6 +567,12 @@ void UIWidget::destroy()
m_destroyed = true;
}
void UIWidget::destroyChildren()
{
while(!m_children.empty())
getFirstChild()->destroy();
}
void UIWidget::setId(const std::string& id)
{
m_id = id;
@ -1108,6 +1113,11 @@ void UIWidget::onFocusChange(bool focused, Fw::FocusReason reason)
callLuaField("onFocusChange", focused, reason);
}
void UIWidget::onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason)
{
callLuaField("onChildFocusChange", focusedChild, unfocusedChild, reason);
}
void UIWidget::onHoverChange(bool hovered)
{
callLuaField("onHoverChange", hovered);
@ -1168,7 +1178,7 @@ bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button)
bool UIWidget::onMouseRelease(const Point& mousePos, Fw::MouseButton button)
{
if(isPressed() && getRect().contains(mousePos))
callLuaField("onClick");
onClick(mousePos);
UIWidgetPtr draggedWidget = g_ui.getDraggingWidget();
if(draggedWidget && button == Fw::MouseLeftButton && (containsPoint(mousePos) || asUIWidget() == g_ui.getRootWidget())) {
@ -1196,6 +1206,11 @@ bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direc
return callLuaField<bool>("onMouseWheel", mousePos, direction);
}
bool UIWidget::onClick(const Point& mousePos)
{
return callLuaField<bool>("onClick", mousePos);
}
bool UIWidget::onDoubleClick(const Point& mousePos)
{
return callLuaField<bool>("onDoubleClick", mousePos);

View File

@ -105,6 +105,7 @@ public:
void ungrabKeyboard();
void bindRectToParent();
void destroy();
void destroyChildren();
void setId(const std::string& id);
void setParent(const UIWidgetPtr& parent);
@ -169,6 +170,7 @@ protected:
virtual void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
virtual void onGeometryChange(const Rect& oldRect, const Rect& newRect);
virtual void onFocusChange(bool focused, Fw::FocusReason reason);
virtual void onChildFocusChange(const UIWidgetPtr& focusedChild, const UIWidgetPtr& unfocusedChild, Fw::FocusReason reason);
virtual void onHoverChange(bool hovered);
virtual void onDragEnter(const Point& mousePos);
virtual void onDragLeave(UIWidgetPtr droppedWidget, const Point& mousePos);
@ -181,6 +183,7 @@ protected:
virtual bool onMouseRelease(const Point& mousePos, Fw::MouseButton button);
virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
virtual bool onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direction);
virtual bool onClick(const Point& mousePos);
virtual bool onDoubleClick(const Point& mousePos);
bool propagateOnKeyText(const std::string& keyText);