Merge with develop
--HG-- branch : sha512-auth
This commit is contained in:
commit
ff7450a22e
72 changed files with 1082 additions and 549 deletions
|
@ -110,6 +110,10 @@ FIND_PACKAGE(Jpeg)
|
|||
|
||||
IF(WITH_STATIC_LIBXML2)
|
||||
SET(LIBXML2_DEFINITIONS ${LIBXML2_DEFINITIONS} -DLIBXML_STATIC)
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
FIND_PACKAGE(LibLZMA REQUIRED)
|
||||
SET(LIBXML2_LIBRARIES ${LIBXML2_LIBRARIES} ${LIBLZMA_LIBRARIES})
|
||||
ENDIF(NOT WIN32 AND NOT APPLE)
|
||||
ENDIF(WITH_STATIC_LIBXML2)
|
||||
|
||||
IF(WITH_STATIC)
|
||||
|
|
|
@ -11,6 +11,12 @@ MACRO(FIND_CORRECT_LUA_VERSION)
|
|||
|
||||
SET(LUA52_LIBRARY "liblua5.2")
|
||||
CHECK_LINKED_LIBRARY(LUABIND_LIBRARY_RELEASE LUA52_LIBRARY LUALIB_FOUND)
|
||||
|
||||
IF(NOT LUALIB_FOUND)
|
||||
# fedora (v20)
|
||||
SET(LUA52_LIBRARY "liblua-5.2")
|
||||
CHECK_LINKED_LIBRARY(LUABIND_LIBRARY_RELEASE LUA52_LIBRARY LUALIB_FOUND)
|
||||
ENDIF(NOT LUALIB_FOUND)
|
||||
|
||||
IF(LUALIB_FOUND)
|
||||
MESSAGE(STATUS "Luabind is using Lua 5.2")
|
||||
|
|
|
@ -285,7 +285,7 @@ namespace NLGUI
|
|||
void addImage(const char *image, bool globalColor, bool reloadImg=false);
|
||||
|
||||
// Add a text area in the current paragraph
|
||||
CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content);
|
||||
CInterfaceGroup *addTextArea (const std::string &templateName, const char *name, uint rows, uint cols, bool multiLine, const ucstring &content, uint maxlength);
|
||||
|
||||
// Add a combo box in the current paragraph
|
||||
CDBGroupComboBox *addComboBox(const std::string &templateName, const char *name);
|
||||
|
@ -557,6 +557,7 @@ namespace NLGUI
|
|||
std::string _TextAreaName;
|
||||
uint _TextAreaRow;
|
||||
uint _TextAreaCols;
|
||||
uint _TextAreaMaxLength;
|
||||
|
||||
// current mode is in select option
|
||||
bool _SelectOption;
|
||||
|
|
|
@ -233,6 +233,9 @@ namespace NLGUI
|
|||
|
||||
virtual void setActive (bool state);
|
||||
|
||||
void setXReal( sint32 x ){ _XReal = x; }
|
||||
void setYReal( sint32 y ){ _YReal = y; }
|
||||
|
||||
void setX (sint32 x) { _X = x; }
|
||||
void setXAndInvalidateCoords (sint32 x) { _X = x; invalidateCoords(); }
|
||||
|
||||
|
|
|
@ -79,6 +79,9 @@ namespace NLGUI
|
|||
bool delElement (const std::string &id, bool noWarning=false);
|
||||
bool delElement (CInterfaceElement *pIE, bool noWarning=false);
|
||||
|
||||
// Take the element from the group, but don't delete it!
|
||||
CInterfaceElement* takeElement( CInterfaceElement *e );
|
||||
|
||||
uint getNumGroup() const { return (uint)_ChildrenGroups.size(); }
|
||||
CInterfaceGroup *getGroup(uint index) const;
|
||||
|
||||
|
|
|
@ -189,6 +189,7 @@ namespace NLGUI
|
|||
HTML_ATTR(TEXTAREA,DISABLED),
|
||||
HTML_ATTR(TEXTAREA,ID),
|
||||
HTML_ATTR(TEXTAREA,LANG),
|
||||
HTML_ATTR(TEXTAREA,MAXLENGTH),
|
||||
HTML_ATTR(TEXTAREA,NAME),
|
||||
HTML_ATTR(TEXTAREA,READONLY),
|
||||
HTML_ATTR(TEXTAREA,ROWS),
|
||||
|
|
|
@ -332,7 +332,13 @@ namespace NLGUI
|
|||
void drawViews( NL3D::UCamera camera );
|
||||
|
||||
bool handleEvent( const CEventDescriptor &evnt );
|
||||
|
||||
|
||||
bool handleSystemEvent( const CEventDescriptor &evnt );
|
||||
|
||||
bool handleKeyboardEvent( const CEventDescriptor &evnt );
|
||||
|
||||
bool handleMouseEvent( const CEventDescriptor &evnt );
|
||||
|
||||
bool handleMouseMoveEvent( const CEventDescriptor &eventDesc );
|
||||
|
||||
// Relative move of pointer
|
||||
|
@ -526,6 +532,11 @@ namespace NLGUI
|
|||
|
||||
NLMISC::CRefPtr< CViewBase > _CapturedView;
|
||||
|
||||
NLMISC::CRefPtr< CInterfaceElement > draggedElement;
|
||||
|
||||
bool startDragging();
|
||||
void stopDragging();
|
||||
|
||||
// What is under pointer
|
||||
std::vector< CViewBase* > _ViewsUnderPointer;
|
||||
std::vector< CCtrlBase* > _CtrlsUnderPointer;
|
||||
|
|
|
@ -1851,6 +1851,9 @@ bool CDriverGL::setMode(const GfxMode& mode)
|
|||
#if defined(NL_OS_WINDOWS)
|
||||
// save relative cursor
|
||||
POINT cursorPos;
|
||||
cursorPos.x = 0;
|
||||
cursorPos.y = 0;
|
||||
|
||||
BOOL cursorPosOk = isSystemCursorInClientArea()
|
||||
&& GetCursorPos(&cursorPos)
|
||||
&& ScreenToClient(_win, &cursorPos);
|
||||
|
|
|
@ -1320,6 +1320,16 @@ namespace NLGUI
|
|||
}
|
||||
}
|
||||
|
||||
// if click, and not frozen, then get the focus
|
||||
if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup && !_Frozen)
|
||||
{
|
||||
_SelectingText = false;
|
||||
if (_SelectCursorPos == _CursorPos)
|
||||
_CurrSelection = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isIn(eventDesc.getX(), eventDesc.getY()))
|
||||
return false;
|
||||
|
||||
|
@ -1329,6 +1339,7 @@ namespace NLGUI
|
|||
_SelectingText = true;
|
||||
stopParentBlink();
|
||||
CWidgetManager::getInstance()->setCaptureKeyboard (this);
|
||||
CWidgetManager::getInstance()->setCapturePointerLeft (this);
|
||||
// set the right cursor position
|
||||
uint newCurPos;
|
||||
bool cursorAtPreviousLineEnd;
|
||||
|
@ -1356,16 +1367,6 @@ namespace NLGUI
|
|||
return true;
|
||||
}
|
||||
|
||||
// if click, and not frozen, then get the focus
|
||||
if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup && !_Frozen)
|
||||
{
|
||||
_SelectingText = false;
|
||||
if (_SelectCursorPos == _CursorPos)
|
||||
_CurrSelection = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (eventDesc.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown)
|
||||
{
|
||||
CWidgetManager::getInstance()->setCapturePointerRight(this);
|
||||
|
|
|
@ -1289,16 +1289,19 @@ namespace NLGUI
|
|||
string name;
|
||||
ucstring ucValue;
|
||||
uint size = 120;
|
||||
uint maxlength = 1024;
|
||||
if (present[MY_HTML_INPUT_NAME] && value[MY_HTML_INPUT_NAME])
|
||||
name = value[MY_HTML_INPUT_NAME];
|
||||
if (present[MY_HTML_INPUT_SIZE] && value[MY_HTML_INPUT_SIZE])
|
||||
fromString(value[MY_HTML_INPUT_SIZE], size);
|
||||
if (present[MY_HTML_INPUT_VALUE] && value[MY_HTML_INPUT_VALUE])
|
||||
ucValue.fromUtf8(value[MY_HTML_INPUT_VALUE]);
|
||||
if (present[MY_HTML_INPUT_MAXLENGTH] && value[MY_HTML_INPUT_MAXLENGTH])
|
||||
fromString(value[MY_HTML_INPUT_MAXLENGTH], maxlength);
|
||||
|
||||
string textTemplate(!templateName.empty() ? templateName : DefaultFormTextGroup);
|
||||
// Add the editbox
|
||||
CInterfaceGroup *textArea = addTextArea (textTemplate, name.c_str (), 1, size/12, false, ucValue);
|
||||
CInterfaceGroup *textArea = addTextArea (textTemplate, name.c_str (), 1, size/12, false, ucValue, maxlength);
|
||||
if (textArea)
|
||||
{
|
||||
// Add the text area to the form
|
||||
|
@ -1553,12 +1556,15 @@ namespace NLGUI
|
|||
_TextAreaRow = 1;
|
||||
_TextAreaCols = 10;
|
||||
_TextAreaContent = "";
|
||||
if (present[HTML_TEXTAREA_NAME] && value[HTML_TEXTAREA_NAME])
|
||||
_TextAreaName = value[HTML_TEXTAREA_NAME];
|
||||
if (present[HTML_TEXTAREA_ROWS] && value[HTML_TEXTAREA_ROWS])
|
||||
fromString(value[HTML_TEXTAREA_ROWS], _TextAreaRow);
|
||||
if (present[HTML_TEXTAREA_COLS] && value[HTML_TEXTAREA_COLS])
|
||||
fromString(value[HTML_TEXTAREA_COLS], _TextAreaCols);
|
||||
_TextAreaMaxLength = 1024;
|
||||
if (present[MY_HTML_TEXTAREA_NAME] && value[MY_HTML_TEXTAREA_NAME])
|
||||
_TextAreaName = value[MY_HTML_TEXTAREA_NAME];
|
||||
if (present[MY_HTML_TEXTAREA_ROWS] && value[MY_HTML_TEXTAREA_ROWS])
|
||||
fromString(value[MY_HTML_TEXTAREA_ROWS], _TextAreaRow);
|
||||
if (present[MY_HTML_TEXTAREA_COLS] && value[MY_HTML_TEXTAREA_COLS])
|
||||
fromString(value[MY_HTML_TEXTAREA_COLS], _TextAreaCols);
|
||||
if (present[MY_HTML_TEXTAREA_MAXLENGTH] && value[MY_HTML_TEXTAREA_MAXLENGTH])
|
||||
fromString(value[MY_HTML_TEXTAREA_MAXLENGTH], _TextAreaMaxLength);
|
||||
|
||||
_TextAreaTemplate = !templateName.empty() ? templateName : DefaultFormTextAreaGroup;
|
||||
_TextArea = true;
|
||||
|
@ -1680,7 +1686,7 @@ namespace NLGUI
|
|||
// nlinfo("textarea name '%s'", _TextAreaName.c_str());
|
||||
// nlinfo("textarea %d %d", _TextAreaRow, _TextAreaCols);
|
||||
// nlinfo("textarea content '%s'", _TextAreaContent.toUtf8().c_str());
|
||||
CInterfaceGroup *textArea = addTextArea (_TextAreaTemplate, _TextAreaName.c_str (), _TextAreaRow, _TextAreaCols, true, _TextAreaContent);
|
||||
CInterfaceGroup *textArea = addTextArea (_TextAreaTemplate, _TextAreaName.c_str (), _TextAreaRow, _TextAreaCols, true, _TextAreaContent, _TextAreaMaxLength);
|
||||
if (textArea)
|
||||
{
|
||||
// Add the text area to the form
|
||||
|
@ -3258,7 +3264,7 @@ namespace NLGUI
|
|||
|
||||
// ***************************************************************************
|
||||
|
||||
CInterfaceGroup *CGroupHTML::addTextArea(const std::string &templateName, const char *name, uint /* rows */, uint cols, bool multiLine, const ucstring &content)
|
||||
CInterfaceGroup *CGroupHTML::addTextArea(const std::string &templateName, const char *name, uint /* rows */, uint cols, bool multiLine, const ucstring &content, uint maxlength)
|
||||
{
|
||||
// In a paragraph ?
|
||||
if (!_Paragraph)
|
||||
|
@ -3280,7 +3286,8 @@ namespace NLGUI
|
|||
templateParams.push_back (std::pair<std::string,std::string> ("multiline", multiLine?"true":"false"));
|
||||
templateParams.push_back (std::pair<std::string,std::string> ("want_return", multiLine?"true":"false"));
|
||||
templateParams.push_back (std::pair<std::string,std::string> ("enter_recover_focus", "false"));
|
||||
templateParams.push_back (std::pair<std::string,std::string> ("max_num_chars", "1024"));
|
||||
if (maxlength > 0)
|
||||
templateParams.push_back (std::pair<std::string,std::string> ("max_num_chars", toString(maxlength)));
|
||||
CInterfaceGroup *textArea = CWidgetManager::getInstance()->getParser()->createGroupInstance (templateName.c_str(),
|
||||
getParagraph()->getId(), templateParams.empty()?NULL:&(templateParams[0]), (uint)templateParams.size());
|
||||
|
||||
|
|
|
@ -1638,6 +1638,32 @@ namespace NLGUI
|
|||
return delView(static_cast<CViewBase*>(pIE));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CInterfaceElement* CInterfaceGroup::takeElement( CInterfaceElement *e )
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
if( e->isGroup() )
|
||||
{
|
||||
ok = delGroup( static_cast< CInterfaceGroup* >( e ), true );
|
||||
}
|
||||
else
|
||||
if( e->isCtrl() )
|
||||
{
|
||||
ok = delCtrl( static_cast< CCtrlBase* >( e ), true );
|
||||
}
|
||||
else
|
||||
if( e->isView() )
|
||||
{
|
||||
ok = delView( static_cast< CViewBase* >( e ), true );
|
||||
}
|
||||
|
||||
if( ok )
|
||||
return e;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CInterfaceGroup::isWindowUnder (sint32 x, sint32 y)
|
||||
{
|
||||
|
|
|
@ -201,6 +201,7 @@ namespace NLGUI
|
|||
HTML_ATTR(TEXTAREA,DISABLED),
|
||||
HTML_ATTR(TEXTAREA,ID),
|
||||
HTML_ATTR(TEXTAREA,LANG),
|
||||
HTML_ATTR(TEXTAREA,MAXLENGTH),
|
||||
HTML_ATTR(TEXTAREA,NAME),
|
||||
HTML_ATTR(TEXTAREA,READONLY),
|
||||
HTML_ATTR(TEXTAREA,ROWS),
|
||||
|
|
|
@ -2039,6 +2039,12 @@ namespace NLGUI
|
|||
}
|
||||
}
|
||||
|
||||
if( draggedElement != NULL )
|
||||
{
|
||||
CInterfaceElement *e = draggedElement;
|
||||
static_cast< CViewBase* >( e )->draw();
|
||||
}
|
||||
|
||||
if ( (nPriority == WIN_PRIORITY_WORLD_SPACE) && !camera.empty())
|
||||
{
|
||||
driver->setMatrixMode2D11();
|
||||
|
@ -2096,448 +2102,22 @@ namespace NLGUI
|
|||
if( activeAnims[i]->isDisableButtons() )
|
||||
return false;
|
||||
|
||||
if( evnt.getType() == CEventDescriptor::system )
|
||||
{
|
||||
const CEventDescriptorSystem &systemEvent = reinterpret_cast< const CEventDescriptorSystem& >( evnt );
|
||||
if( systemEvent.getEventTypeExtended() == CEventDescriptorSystem::setfocus )
|
||||
{
|
||||
if( getCapturePointerLeft() != NULL )
|
||||
{
|
||||
getCapturePointerLeft()->handleEvent( evnt );
|
||||
setCapturePointerLeft( NULL );
|
||||
}
|
||||
|
||||
if( getCapturePointerRight() != NULL )
|
||||
{
|
||||
getCapturePointerRight()->handleEvent( evnt );
|
||||
setCapturePointerRight( NULL );
|
||||
}
|
||||
|
||||
if( _CapturedView != NULL )
|
||||
{
|
||||
_CapturedView->handleEvent( evnt );
|
||||
_CapturedView = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
|
||||
CViewPointer *_Pointer = static_cast< CViewPointer* >( getPointer() );
|
||||
|
||||
if( evnt.getType() == CEventDescriptor::system )
|
||||
{
|
||||
handleSystemEvent( evnt );
|
||||
}
|
||||
else
|
||||
if (evnt.getType() == CEventDescriptor::key)
|
||||
{
|
||||
CEventDescriptorKey &eventDesc = (CEventDescriptorKey&)evnt;
|
||||
//_LastEventKeyDesc = eventDesc;
|
||||
|
||||
// Any Key event disable the ContextHelp
|
||||
disableContextHelp();
|
||||
|
||||
// Hide menu if the key is pushed
|
||||
// if ((eventDesc.getKeyEventType() == CEventDescriptorKey::keydown) && !_ModalStack.empty() && !eventDesc.getKeyAlt() && !eventDesc.getKeyCtrl() && !eventDesc.getKeyShift())
|
||||
// Hide menu (or popup menu) is ESCAPE pressed
|
||||
if( eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyESCAPE )
|
||||
{
|
||||
if( hasModal() )
|
||||
{
|
||||
SModalWndInfo mwi = getModal();
|
||||
if (mwi.ModalExitKeyPushed)
|
||||
disableModalWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// Manage "quit window" If the Key is ESCAPE, no captureKeyboard
|
||||
if( eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyESCAPE )
|
||||
{
|
||||
// Get the last escapable active top window. NB: this is ergonomically better.
|
||||
CInterfaceGroup *win= getLastEscapableTopWindow();
|
||||
if( win )
|
||||
{
|
||||
// If the window is a modal, must pop it.
|
||||
if( dynamic_cast<CGroupModal*>(win) )
|
||||
{
|
||||
if(!win->getAHOnEscape().empty())
|
||||
CAHManager::getInstance()->runActionHandler(win->getAHOnEscape(), win, win->getAHOnEscapeParams());
|
||||
popModalWindow();
|
||||
handled= true;
|
||||
}
|
||||
// else just disable it.
|
||||
// Special case: leave the escape Key to the CaptureKeyboard .
|
||||
else if( !getCaptureKeyboard() )
|
||||
{
|
||||
if(!win->getAHOnEscape().empty())
|
||||
CAHManager::getInstance()->runActionHandler(win->getAHOnEscape(), win, win->getAHOnEscapeParams());
|
||||
win->setActive(false);
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Manage complex "Enter"
|
||||
if (eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyRETURN)
|
||||
{
|
||||
// If the top window has Enter AH
|
||||
CInterfaceGroup *tw= getTopWindow();
|
||||
if(tw && !tw->getAHOnEnter().empty())
|
||||
{
|
||||
// if the captured keyboard is in this Modal window, then must handle him in priority
|
||||
if( getCaptureKeyboard() && getCaptureKeyboard()->getRootWindow()==tw)
|
||||
{
|
||||
bool result = getCaptureKeyboard()->handleEvent(evnt);
|
||||
CDBManager::getInstance()->flushObserverCalls();
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The window or modal control the OnEnter. Execute, and don't go to the chat.
|
||||
CAHManager::getInstance()->runActionHandler(tw->getAHOnEnter(), tw, tw->getAHOnEnterParams());
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
|
||||
// else the 'return' key bring back to the last edit box (if possible)
|
||||
CCtrlBase *oldCapture = getOldCaptureKeyboard() ? getOldCaptureKeyboard() : getDefaultCaptureKeyboard();
|
||||
if ( getCaptureKeyboard() == NULL && oldCapture && !handled)
|
||||
{
|
||||
/* If the editbox does not want to recover focus, then abort. This possibility is normaly avoided
|
||||
through setCaptureKeyboard() which already test getRecoverFocusOnEnter(), but it is still possible
|
||||
for the default capture (main chat) or the old captured window to not want to recover
|
||||
(temporary Read Only chat for instance)
|
||||
*/
|
||||
if(!dynamic_cast<CGroupEditBoxBase*>(oldCapture) ||
|
||||
dynamic_cast<CGroupEditBoxBase*>(oldCapture)->getRecoverFocusOnEnter())
|
||||
{
|
||||
setCaptureKeyboard( oldCapture );
|
||||
notifyElementCaptured(getCaptureKeyboard() );
|
||||
// make sure all parent windows are active
|
||||
CCtrlBase *cb = getCaptureKeyboard();
|
||||
CGroupContainer *lastContainer = NULL;
|
||||
for(;;)
|
||||
{
|
||||
CGroupContainer *gc = dynamic_cast<CGroupContainer *>(cb);
|
||||
if (gc) lastContainer = gc;
|
||||
cb->forceOpen();
|
||||
if (cb->getParent())
|
||||
{
|
||||
cb = cb->getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->invalidateCoords();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastContainer)
|
||||
{
|
||||
setTopWindow(lastContainer);
|
||||
lastContainer->enableBlink(1);
|
||||
}
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General case: handle it in the Captured keyboard
|
||||
if ( getCaptureKeyboard() != NULL && !handled)
|
||||
{
|
||||
bool result = getCaptureKeyboard()->handleEvent(evnt);
|
||||
CDBManager::getInstance()->flushObserverCalls();
|
||||
return result;
|
||||
}
|
||||
|
||||
lastKeyEvent = eventDesc;
|
||||
handled = handleKeyboardEvent( evnt );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////// Keyboard handling ends here ////////////////////////////////////
|
||||
|
||||
else if (evnt.getType() == CEventDescriptor::mouse )
|
||||
{
|
||||
CEventDescriptorMouse &eventDesc = (CEventDescriptorMouse&)evnt;
|
||||
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() | NLMISC::leftButton ) );
|
||||
else
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() | NLMISC::rightButton ) );
|
||||
else
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() & ~NLMISC::leftButton ) );
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() & ~NLMISC::rightButton ) );
|
||||
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mousemove )
|
||||
handleMouseMoveEvent( eventDesc );
|
||||
|
||||
eventDesc.setX( _Pointer->getX() );
|
||||
eventDesc.setY( _Pointer->getY() );
|
||||
|
||||
if( isMouseHandlingEnabled() )
|
||||
{
|
||||
// First thing to do : Capture handling
|
||||
if ( getCapturePointerLeft() != NULL)
|
||||
handled|= getCapturePointerLeft()->handleEvent(evnt);
|
||||
|
||||
if ( getCapturePointerRight() != NULL &&
|
||||
getCapturePointerLeft() != getCapturePointerRight() )
|
||||
handled|= getCapturePointerRight()->handleEvent(evnt);
|
||||
|
||||
if( _CapturedView != NULL )
|
||||
_CapturedView->handleEvent( evnt );
|
||||
|
||||
CInterfaceGroup *ptr = getWindowUnder (eventDesc.getX(), eventDesc.getY());
|
||||
setCurrentWindowUnder( ptr );
|
||||
|
||||
// Any Mouse event but move disable the ContextHelp
|
||||
if(eventDesc.getEventTypeExtended() != CEventDescriptorMouse::mousemove)
|
||||
{
|
||||
disableContextHelp();
|
||||
}
|
||||
|
||||
// get the group under the mouse
|
||||
CInterfaceGroup *pNewCurrentWnd = getCurrentWindowUnder();
|
||||
setMouseOverWindow( pNewCurrentWnd != NULL );
|
||||
|
||||
|
||||
NLMISC::CRefPtr<CGroupModal> clickedOutModalWindow;
|
||||
|
||||
// modal special features
|
||||
if ( hasModal() )
|
||||
{
|
||||
CWidgetManager::SModalWndInfo mwi = getModal();
|
||||
if(mwi.ModalWindow)
|
||||
{
|
||||
// If we are not in "click out" mode so we dont handle controls other than those of the modal
|
||||
if (pNewCurrentWnd != mwi.ModalWindow && !mwi.ModalExitClickOut)
|
||||
{
|
||||
pNewCurrentWnd = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is a handler on click out launch it
|
||||
if (pNewCurrentWnd != mwi.ModalWindow)
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown ||
|
||||
(eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown))
|
||||
if (!mwi.ModalHandlerClickOut.empty())
|
||||
CAHManager::getInstance()->runActionHandler(mwi.ModalHandlerClickOut,NULL,mwi.ModalClickOutParams);
|
||||
|
||||
// If the current window is not the modal and if must quit on click out
|
||||
if(pNewCurrentWnd != mwi.ModalWindow && mwi.ModalExitClickOut)
|
||||
{
|
||||
// NB: don't force handle==true because to quit a modal does not avoid other actions
|
||||
|
||||
// quit if click outside
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown ||
|
||||
(eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown))
|
||||
{
|
||||
clickedOutModalWindow = dynamic_cast<CGroupModal *>((CInterfaceGroup*)mwi.ModalWindow);
|
||||
// disable the modal
|
||||
popModalWindow();
|
||||
if ( hasModal() )
|
||||
{
|
||||
// don't handle event unless it is a previous modal window
|
||||
if( !isPreviousModal( pNewCurrentWnd ) )
|
||||
pNewCurrentWnd = NULL; // can't handle event before we have left all modal windows
|
||||
}
|
||||
movePointer (0,0); // Reget controls under pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Manage LeftClick.
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown)
|
||||
{
|
||||
if ((pNewCurrentWnd != NULL) && (!hasModal()) && (pNewCurrentWnd->getOverlappable()))
|
||||
{
|
||||
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pNewCurrentWnd);
|
||||
if (pGC != NULL)
|
||||
{
|
||||
if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
}
|
||||
|
||||
bool captured = false;
|
||||
|
||||
// must not capture a new element if a sheet is currentlty being dragged.
|
||||
// This may happen when alt-tab has been used => the sheet is dragged but the left button is up
|
||||
if (!CCtrlDraggable::getDraggedSheet())
|
||||
{
|
||||
// Take the top most control.
|
||||
uint nMaxDepth = 0;
|
||||
const std::vector< CCtrlBase* >& _CtrlsUnderPointer = getCtrlsUnderPointer();
|
||||
for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--)
|
||||
{
|
||||
CCtrlBase *ctrl= _CtrlsUnderPointer[i];
|
||||
if (ctrl && ctrl->isCapturable() && ctrl->isInGroup( pNewCurrentWnd ) )
|
||||
{
|
||||
uint d = ctrl->getDepth( pNewCurrentWnd );
|
||||
if (d > nMaxDepth)
|
||||
{
|
||||
nMaxDepth = d;
|
||||
setCapturePointerLeft( ctrl );
|
||||
captured = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( CInterfaceElement::getEditorMode() && !captured )
|
||||
{
|
||||
for( sint32 i = _ViewsUnderPointer.size()-1; i >= 0; i-- )
|
||||
{
|
||||
CViewBase *v = _ViewsUnderPointer[i];
|
||||
if( ( v != NULL ) && v->isInGroup( pNewCurrentWnd ) )
|
||||
{
|
||||
_CapturedView = v;
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notifyElementCaptured( getCapturePointerLeft() );
|
||||
if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty())
|
||||
{
|
||||
CAHManager::getInstance()->runActionHandler(clickedOutModalWindow->OnPostClickOut, getCapturePointerLeft(), clickedOutModalWindow->OnPostClickOutParams);
|
||||
}
|
||||
}
|
||||
//if found
|
||||
if ( captured )
|
||||
{
|
||||
// consider clicking on a control implies handling of the event.
|
||||
handled= true;
|
||||
|
||||
// handle the capture
|
||||
if( getCapturePointerLeft() != NULL )
|
||||
getCapturePointerLeft()->handleEvent(evnt);
|
||||
else
|
||||
_CapturedView->handleEvent( evnt );
|
||||
}
|
||||
}
|
||||
|
||||
// Manage RightClick
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown)
|
||||
{
|
||||
if ((pNewCurrentWnd != NULL) && (!hasModal()) && (pNewCurrentWnd->getOverlappable()))
|
||||
{
|
||||
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pNewCurrentWnd);
|
||||
if (pGC != NULL)
|
||||
{
|
||||
if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Take the top most control.
|
||||
{
|
||||
uint nMaxDepth = 0;
|
||||
const std::vector< CCtrlBase* >& _CtrlsUnderPointer = getCtrlsUnderPointer();
|
||||
for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--)
|
||||
{
|
||||
CCtrlBase *ctrl= _CtrlsUnderPointer[i];
|
||||
if (ctrl && ctrl->isCapturable() && ctrl->isInGroup( pNewCurrentWnd ) )
|
||||
{
|
||||
uint d = ctrl->getDepth( pNewCurrentWnd );
|
||||
if (d > nMaxDepth)
|
||||
{
|
||||
nMaxDepth = d;
|
||||
setCapturePointerRight( ctrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
notifyElementCaptured( getCapturePointerRight() );
|
||||
if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty())
|
||||
{
|
||||
CAHManager::getInstance()->runActionHandler(clickedOutModalWindow->OnPostClickOut, getCapturePointerRight(), clickedOutModalWindow->OnPostClickOutParams);
|
||||
}
|
||||
}
|
||||
//if found
|
||||
if ( getCapturePointerRight() != NULL)
|
||||
{
|
||||
// handle the capture
|
||||
handled |= getCapturePointerRight()->handleEvent(evnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup)
|
||||
{
|
||||
if (!handled)
|
||||
if (pNewCurrentWnd != NULL)
|
||||
pNewCurrentWnd->handleEvent(evnt);
|
||||
if ( getCapturePointerRight() != NULL)
|
||||
{
|
||||
setCapturePointerRight(NULL);
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
|
||||
// window handling. if not handled by a control
|
||||
if (!handled)
|
||||
{
|
||||
if (((pNewCurrentWnd != NULL) && !hasModal()) ||
|
||||
((hasModal() && getModal().ModalWindow == pNewCurrentWnd)))
|
||||
{
|
||||
CEventDescriptorMouse ev2 = eventDesc;
|
||||
sint32 x= eventDesc.getX(), y = eventDesc.getY();
|
||||
if (pNewCurrentWnd)
|
||||
{
|
||||
pNewCurrentWnd->absoluteToRelative (x, y);
|
||||
ev2.setX (x); ev2.setY (y);
|
||||
handled|= pNewCurrentWnd->handleEvent (ev2);
|
||||
}
|
||||
|
||||
// After handle event of a left click, may set window Top if movable (infos etc...)
|
||||
//if( (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown) && pNewCurrentWnd->isMovable() )
|
||||
// setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Put here to let a chance to the window to handle if the capture dont
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup)
|
||||
{
|
||||
if ( getCapturePointerLeft() != NULL)
|
||||
{
|
||||
setCapturePointerLeft(NULL);
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the current window is the modal, may Modal quit. Do it after standard event handle
|
||||
if(hasModal() && pNewCurrentWnd == getModal().ModalWindow)
|
||||
{
|
||||
// NB: don't force handle==true because to quit a modal does not avoid other actions
|
||||
CWidgetManager::SModalWndInfo mwi = getModal();
|
||||
// and if must quit on click right
|
||||
if(mwi.ModalExitClickR)
|
||||
{
|
||||
// quit if click right
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup)
|
||||
// disable the modal
|
||||
disableModalWindow();
|
||||
}
|
||||
|
||||
// and if must quit on click left
|
||||
if(mwi.ModalExitClickL)
|
||||
{
|
||||
// quit if click right
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup)
|
||||
// disable the modal
|
||||
disableModalWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// If the mouse is over a window, always consider the event is taken (avoid click behind)
|
||||
handled|= isMouseOverWindow();
|
||||
}
|
||||
handled = handleMouseEvent( evnt );
|
||||
}
|
||||
|
||||
CDBManager::getInstance()->flushObserverCalls();
|
||||
|
@ -2545,6 +2125,467 @@ namespace NLGUI
|
|||
return handled;
|
||||
}
|
||||
|
||||
bool CWidgetManager::handleSystemEvent( const CEventDescriptor &evnt )
|
||||
{
|
||||
const CEventDescriptorSystem &systemEvent = reinterpret_cast< const CEventDescriptorSystem& >( evnt );
|
||||
if( systemEvent.getEventTypeExtended() == CEventDescriptorSystem::setfocus )
|
||||
{
|
||||
if( getCapturePointerLeft() != NULL )
|
||||
{
|
||||
getCapturePointerLeft()->handleEvent( evnt );
|
||||
setCapturePointerLeft( NULL );
|
||||
}
|
||||
|
||||
if( getCapturePointerRight() != NULL )
|
||||
{
|
||||
getCapturePointerRight()->handleEvent( evnt );
|
||||
setCapturePointerRight( NULL );
|
||||
}
|
||||
|
||||
if( _CapturedView != NULL )
|
||||
{
|
||||
_CapturedView->handleEvent( evnt );
|
||||
_CapturedView = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWidgetManager::handleKeyboardEvent( const CEventDescriptor &evnt )
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
CEventDescriptorKey &eventDesc = (CEventDescriptorKey&)evnt;
|
||||
|
||||
//_LastEventKeyDesc = eventDesc;
|
||||
|
||||
// Any Key event disable the ContextHelp
|
||||
disableContextHelp();
|
||||
|
||||
// Hide menu if the key is pushed
|
||||
// if ((eventDesc.getKeyEventType() == CEventDescriptorKey::keydown) && !_ModalStack.empty() && !eventDesc.getKeyAlt() && !eventDesc.getKeyCtrl() && !eventDesc.getKeyShift())
|
||||
// Hide menu (or popup menu) is ESCAPE pressed
|
||||
if( eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyESCAPE )
|
||||
{
|
||||
if( hasModal() )
|
||||
{
|
||||
SModalWndInfo mwi = getModal();
|
||||
if (mwi.ModalExitKeyPushed)
|
||||
disableModalWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// Manage "quit window" If the Key is ESCAPE, no captureKeyboard
|
||||
if( eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyESCAPE )
|
||||
{
|
||||
// Get the last escapable active top window. NB: this is ergonomically better.
|
||||
CInterfaceGroup *win= getLastEscapableTopWindow();
|
||||
if( win )
|
||||
{
|
||||
// If the window is a modal, must pop it.
|
||||
if( dynamic_cast<CGroupModal*>(win) )
|
||||
{
|
||||
if(!win->getAHOnEscape().empty())
|
||||
CAHManager::getInstance()->runActionHandler(win->getAHOnEscape(), win, win->getAHOnEscapeParams());
|
||||
popModalWindow();
|
||||
handled= true;
|
||||
}
|
||||
// else just disable it.
|
||||
// Special case: leave the escape Key to the CaptureKeyboard .
|
||||
else if( !getCaptureKeyboard() )
|
||||
{
|
||||
if(!win->getAHOnEscape().empty())
|
||||
CAHManager::getInstance()->runActionHandler(win->getAHOnEscape(), win, win->getAHOnEscapeParams());
|
||||
win->setActive(false);
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Manage complex "Enter"
|
||||
if (eventDesc.getKeyEventType() == CEventDescriptorKey::keychar && eventDesc.getChar() == NLMISC::KeyRETURN)
|
||||
{
|
||||
// If the top window has Enter AH
|
||||
CInterfaceGroup *tw= getTopWindow();
|
||||
if(tw && !tw->getAHOnEnter().empty())
|
||||
{
|
||||
// if the captured keyboard is in this Modal window, then must handle him in priority
|
||||
if( getCaptureKeyboard() && getCaptureKeyboard()->getRootWindow()==tw)
|
||||
{
|
||||
bool result = getCaptureKeyboard()->handleEvent(evnt);
|
||||
CDBManager::getInstance()->flushObserverCalls();
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The window or modal control the OnEnter. Execute, and don't go to the chat.
|
||||
CAHManager::getInstance()->runActionHandler(tw->getAHOnEnter(), tw, tw->getAHOnEnterParams());
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
|
||||
// else the 'return' key bring back to the last edit box (if possible)
|
||||
CCtrlBase *oldCapture = getOldCaptureKeyboard() ? getOldCaptureKeyboard() : getDefaultCaptureKeyboard();
|
||||
if ( getCaptureKeyboard() == NULL && oldCapture && !handled)
|
||||
{
|
||||
/* If the editbox does not want to recover focus, then abort. This possibility is normaly avoided
|
||||
through setCaptureKeyboard() which already test getRecoverFocusOnEnter(), but it is still possible
|
||||
for the default capture (main chat) or the old captured window to not want to recover
|
||||
(temporary Read Only chat for instance)
|
||||
*/
|
||||
if(!dynamic_cast<CGroupEditBoxBase*>(oldCapture) ||
|
||||
dynamic_cast<CGroupEditBoxBase*>(oldCapture)->getRecoverFocusOnEnter())
|
||||
{
|
||||
setCaptureKeyboard( oldCapture );
|
||||
notifyElementCaptured(getCaptureKeyboard() );
|
||||
// make sure all parent windows are active
|
||||
CCtrlBase *cb = getCaptureKeyboard();
|
||||
CGroupContainer *lastContainer = NULL;
|
||||
for(;;)
|
||||
{
|
||||
CGroupContainer *gc = dynamic_cast<CGroupContainer *>(cb);
|
||||
if (gc) lastContainer = gc;
|
||||
cb->forceOpen();
|
||||
if (cb->getParent())
|
||||
{
|
||||
cb = cb->getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->invalidateCoords();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastContainer)
|
||||
{
|
||||
setTopWindow(lastContainer);
|
||||
lastContainer->enableBlink(1);
|
||||
}
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// General case: handle it in the Captured keyboard
|
||||
if ( getCaptureKeyboard() != NULL && !handled)
|
||||
{
|
||||
bool result = getCaptureKeyboard()->handleEvent(evnt);
|
||||
CDBManager::getInstance()->flushObserverCalls();
|
||||
return result;
|
||||
}
|
||||
|
||||
lastKeyEvent = eventDesc;
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool CWidgetManager::handleMouseEvent( const CEventDescriptor &evnt )
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
CEventDescriptorMouse &eventDesc = (CEventDescriptorMouse&)evnt;
|
||||
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() | NLMISC::leftButton ) );
|
||||
else
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() | NLMISC::rightButton ) );
|
||||
else
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() & ~NLMISC::leftButton ) );
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup )
|
||||
_Pointer->setButtonState( static_cast< NLMISC::TMouseButton >( _Pointer->getButtonState() & ~NLMISC::rightButton ) );
|
||||
|
||||
if( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mousemove )
|
||||
handleMouseMoveEvent( eventDesc );
|
||||
|
||||
eventDesc.setX( _Pointer->getX() );
|
||||
eventDesc.setY( _Pointer->getY() );
|
||||
|
||||
if( isMouseHandlingEnabled() )
|
||||
{
|
||||
// First thing to do : Capture handling
|
||||
if ( getCapturePointerLeft() != NULL)
|
||||
handled|= getCapturePointerLeft()->handleEvent(evnt);
|
||||
|
||||
if ( getCapturePointerRight() != NULL &&
|
||||
getCapturePointerLeft() != getCapturePointerRight() )
|
||||
handled|= getCapturePointerRight()->handleEvent(evnt);
|
||||
|
||||
if( _CapturedView != NULL &&
|
||||
_CapturedView != getCapturePointerLeft() &&
|
||||
_CapturedView != getCapturePointerRight() )
|
||||
_CapturedView->handleEvent( evnt );
|
||||
|
||||
CInterfaceGroup *ptr = getWindowUnder (eventDesc.getX(), eventDesc.getY());
|
||||
setCurrentWindowUnder( ptr );
|
||||
|
||||
// Any Mouse event but move disable the ContextHelp
|
||||
if(eventDesc.getEventTypeExtended() != CEventDescriptorMouse::mousemove)
|
||||
{
|
||||
disableContextHelp();
|
||||
}
|
||||
|
||||
// get the group under the mouse
|
||||
CInterfaceGroup *pNewCurrentWnd = getCurrentWindowUnder();
|
||||
setMouseOverWindow( pNewCurrentWnd != NULL );
|
||||
|
||||
|
||||
NLMISC::CRefPtr<CGroupModal> clickedOutModalWindow;
|
||||
|
||||
// modal special features
|
||||
if ( hasModal() )
|
||||
{
|
||||
CWidgetManager::SModalWndInfo mwi = getModal();
|
||||
if(mwi.ModalWindow)
|
||||
{
|
||||
// If we are not in "click out" mode so we dont handle controls other than those of the modal
|
||||
if (pNewCurrentWnd != mwi.ModalWindow && !mwi.ModalExitClickOut)
|
||||
{
|
||||
pNewCurrentWnd = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there is a handler on click out launch it
|
||||
if (pNewCurrentWnd != mwi.ModalWindow)
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown ||
|
||||
(eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown))
|
||||
if (!mwi.ModalHandlerClickOut.empty())
|
||||
CAHManager::getInstance()->runActionHandler(mwi.ModalHandlerClickOut,NULL,mwi.ModalClickOutParams);
|
||||
|
||||
// If the current window is not the modal and if must quit on click out
|
||||
if(pNewCurrentWnd != mwi.ModalWindow && mwi.ModalExitClickOut)
|
||||
{
|
||||
// NB: don't force handle==true because to quit a modal does not avoid other actions
|
||||
|
||||
// quit if click outside
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown ||
|
||||
(eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown))
|
||||
{
|
||||
clickedOutModalWindow = dynamic_cast<CGroupModal *>((CInterfaceGroup*)mwi.ModalWindow);
|
||||
// disable the modal
|
||||
popModalWindow();
|
||||
if ( hasModal() )
|
||||
{
|
||||
// don't handle event unless it is a previous modal window
|
||||
if( !isPreviousModal( pNewCurrentWnd ) )
|
||||
pNewCurrentWnd = NULL; // can't handle event before we have left all modal windows
|
||||
}
|
||||
movePointer (0,0); // Reget controls under pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Manage LeftClick.
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown)
|
||||
{
|
||||
if ((pNewCurrentWnd != NULL) && (!hasModal()) && (pNewCurrentWnd->getOverlappable()))
|
||||
{
|
||||
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pNewCurrentWnd);
|
||||
if (pGC != NULL)
|
||||
{
|
||||
if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
}
|
||||
|
||||
bool captured = false;
|
||||
|
||||
// must not capture a new element if a sheet is currentlty being dragged.
|
||||
// This may happen when alt-tab has been used => the sheet is dragged but the left button is up
|
||||
if (!CCtrlDraggable::getDraggedSheet())
|
||||
{
|
||||
// Take the top most control.
|
||||
uint nMaxDepth = 0;
|
||||
const std::vector< CCtrlBase* >& _CtrlsUnderPointer = getCtrlsUnderPointer();
|
||||
for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--)
|
||||
{
|
||||
CCtrlBase *ctrl= _CtrlsUnderPointer[i];
|
||||
if (ctrl && ctrl->isCapturable() && ctrl->isInGroup( pNewCurrentWnd ) )
|
||||
{
|
||||
uint d = ctrl->getDepth( pNewCurrentWnd );
|
||||
if (d > nMaxDepth)
|
||||
{
|
||||
nMaxDepth = d;
|
||||
setCapturePointerLeft( ctrl );
|
||||
captured = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( CInterfaceElement::getEditorMode() && !captured )
|
||||
{
|
||||
for( sint32 i = _ViewsUnderPointer.size()-1; i >= 0; i-- )
|
||||
{
|
||||
CViewBase *v = _ViewsUnderPointer[i];
|
||||
if( ( v != NULL ) && v->isInGroup( pNewCurrentWnd ) )
|
||||
{
|
||||
_CapturedView = v;
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notifyElementCaptured( getCapturePointerLeft() );
|
||||
if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty())
|
||||
{
|
||||
CAHManager::getInstance()->runActionHandler(clickedOutModalWindow->OnPostClickOut, getCapturePointerLeft(), clickedOutModalWindow->OnPostClickOutParams);
|
||||
}
|
||||
}
|
||||
//if found
|
||||
if ( captured )
|
||||
{
|
||||
// consider clicking on a control implies handling of the event.
|
||||
handled= true;
|
||||
|
||||
if( getCapturePointerLeft() != NULL )
|
||||
_CapturedView = getCapturePointerLeft();
|
||||
|
||||
// handle the capture
|
||||
_CapturedView->handleEvent( evnt );
|
||||
}
|
||||
}
|
||||
|
||||
// Manage RightClick
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown)
|
||||
{
|
||||
if ((pNewCurrentWnd != NULL) && (!hasModal()) && (pNewCurrentWnd->getOverlappable()))
|
||||
{
|
||||
CGroupContainer *pGC = dynamic_cast<CGroupContainer*>(pNewCurrentWnd);
|
||||
if (pGC != NULL)
|
||||
{
|
||||
if (!pGC->isGrayed()) setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Take the top most control.
|
||||
{
|
||||
uint nMaxDepth = 0;
|
||||
const std::vector< CCtrlBase* >& _CtrlsUnderPointer = getCtrlsUnderPointer();
|
||||
for (sint32 i = (sint32)_CtrlsUnderPointer.size()-1; i >= 0; i--)
|
||||
{
|
||||
CCtrlBase *ctrl= _CtrlsUnderPointer[i];
|
||||
if (ctrl && ctrl->isCapturable() && ctrl->isInGroup( pNewCurrentWnd ) )
|
||||
{
|
||||
uint d = ctrl->getDepth( pNewCurrentWnd );
|
||||
if (d > nMaxDepth)
|
||||
{
|
||||
nMaxDepth = d;
|
||||
setCapturePointerRight( ctrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
notifyElementCaptured( getCapturePointerRight() );
|
||||
if (clickedOutModalWindow && !clickedOutModalWindow->OnPostClickOut.empty())
|
||||
{
|
||||
CAHManager::getInstance()->runActionHandler(clickedOutModalWindow->OnPostClickOut, getCapturePointerRight(), clickedOutModalWindow->OnPostClickOutParams);
|
||||
}
|
||||
}
|
||||
//if found
|
||||
if ( getCapturePointerRight() != NULL)
|
||||
{
|
||||
// handle the capture
|
||||
handled |= getCapturePointerRight()->handleEvent(evnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup)
|
||||
{
|
||||
if (!handled)
|
||||
if (pNewCurrentWnd != NULL)
|
||||
pNewCurrentWnd->handleEvent(evnt);
|
||||
if ( getCapturePointerRight() != NULL)
|
||||
{
|
||||
setCapturePointerRight(NULL);
|
||||
handled= true;
|
||||
}
|
||||
}
|
||||
|
||||
// window handling. if not handled by a control
|
||||
if (!handled)
|
||||
{
|
||||
if (((pNewCurrentWnd != NULL) && !hasModal()) ||
|
||||
((hasModal() && getModal().ModalWindow == pNewCurrentWnd)))
|
||||
{
|
||||
CEventDescriptorMouse ev2 = eventDesc;
|
||||
sint32 x= eventDesc.getX(), y = eventDesc.getY();
|
||||
if (pNewCurrentWnd)
|
||||
{
|
||||
pNewCurrentWnd->absoluteToRelative (x, y);
|
||||
ev2.setX (x); ev2.setY (y);
|
||||
handled|= pNewCurrentWnd->handleEvent (ev2);
|
||||
}
|
||||
|
||||
// After handle event of a left click, may set window Top if movable (infos etc...)
|
||||
//if( (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftdown) && pNewCurrentWnd->isMovable() )
|
||||
// setTopWindow(pNewCurrentWnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Put here to let a chance to the window to handle if the capture dont
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup)
|
||||
{
|
||||
if ( getCapturePointerLeft() != NULL)
|
||||
{
|
||||
if( !handled )
|
||||
{
|
||||
CCtrlBase *c = getCapturePointerLeft();
|
||||
c->handleEvent( evnt );
|
||||
}
|
||||
|
||||
setCapturePointerLeft(NULL);
|
||||
handled = true;
|
||||
}
|
||||
|
||||
_CapturedView = NULL;
|
||||
|
||||
if( CInterfaceElement::getEditorMode() )
|
||||
stopDragging();
|
||||
}
|
||||
|
||||
|
||||
// If the current window is the modal, may Modal quit. Do it after standard event handle
|
||||
if(hasModal() && pNewCurrentWnd == getModal().ModalWindow)
|
||||
{
|
||||
// NB: don't force handle==true because to quit a modal does not avoid other actions
|
||||
CWidgetManager::SModalWndInfo mwi = getModal();
|
||||
// and if must quit on click right
|
||||
if(mwi.ModalExitClickR)
|
||||
{
|
||||
// quit if click right
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup)
|
||||
// disable the modal
|
||||
disableModalWindow();
|
||||
}
|
||||
|
||||
// and if must quit on click left
|
||||
if(mwi.ModalExitClickL)
|
||||
{
|
||||
// quit if click right
|
||||
if (eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouseleftup)
|
||||
// disable the modal
|
||||
disableModalWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// If the mouse is over a window, always consider the event is taken (avoid click behind)
|
||||
handled|= isMouseOverWindow();
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool CWidgetManager::handleMouseMoveEvent( const CEventDescriptor &eventDesc )
|
||||
{
|
||||
|
@ -2580,8 +2621,52 @@ namespace NLGUI
|
|||
ve.setY( getPointer()->getY() );
|
||||
}
|
||||
|
||||
if( CInterfaceElement::getEditorMode() )
|
||||
{
|
||||
if( ( _CapturedView != NULL ) && ( draggedElement == NULL ) )
|
||||
{
|
||||
startDragging();
|
||||
}
|
||||
else
|
||||
if( draggedElement != NULL )
|
||||
{
|
||||
draggedElement->setXReal( newX );
|
||||
draggedElement->setYReal( newY );
|
||||
draggedElement->invalidateCoords();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool CWidgetManager::startDragging()
|
||||
{
|
||||
CInterfaceElement *e = NULL;
|
||||
|
||||
CInterfaceGroup *g = _CapturedView->getParent();
|
||||
if( g != NULL )
|
||||
{
|
||||
e = g->takeElement( _CapturedView );
|
||||
if( e == NULL )
|
||||
{
|
||||
nlinfo( "Something went horribly wrong :(" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
e = _CapturedView;
|
||||
|
||||
e->setParent( NULL );
|
||||
draggedElement = e;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWidgetManager::stopDragging()
|
||||
{
|
||||
draggedElement = NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CWidgetManager::movePointer (sint32 dx, sint32 dy)
|
||||
|
|
|
@ -2738,8 +2738,17 @@ CPrimitiveContext::CPrimitiveContext():
|
|||
}
|
||||
|
||||
|
||||
static bool LIGORegistered = false;
|
||||
|
||||
|
||||
void Register ()
|
||||
{
|
||||
if( LIGORegistered )
|
||||
{
|
||||
nlinfo( "LIGO classes have already been registered." );
|
||||
return;
|
||||
}
|
||||
|
||||
NLMISC_REGISTER_CLASS(CPropertyString);
|
||||
NLMISC_REGISTER_CLASS(CPropertyStringArray);
|
||||
NLMISC_REGISTER_CLASS(CPropertyColor);
|
||||
|
@ -2748,6 +2757,8 @@ void Register ()
|
|||
NLMISC_REGISTER_CLASS(CPrimPath);
|
||||
NLMISC_REGISTER_CLASS(CPrimZone);
|
||||
NLMISC_REGISTER_CLASS(CPrimAlias);
|
||||
|
||||
LIGORegistered = true;
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
|
|
|
@ -52,6 +52,10 @@ if not os.path.isfile(ClientDevDirectory + "/client.cfg"):
|
|||
cfg.write("PreDataPath = {\n")
|
||||
cfg.write("\t\"" + InstallDirectory + "\", \"user\", \"patch\", \"data\", \"examples\" \n")
|
||||
cfg.write("};\n")
|
||||
cfg.write("PatchWanted = 0;\n")
|
||||
cfg.write("DisplayLuaDebugInfo = 1;\n")
|
||||
cfg.write("AllowDebugLua = 1;\n")
|
||||
cfg.write("FullScreen = 0;\n")
|
||||
printLog(log, "")
|
||||
|
||||
printLog(log, ">>> Install data <<<")
|
||||
|
|
11
code/nel/tools/build_gamedata/characters_dev.bat
Normal file
11
code/nel/tools/build_gamedata/characters_dev.bat
Normal file
|
@ -0,0 +1,11 @@
|
|||
title Ryzom Core: 1_export.py (CHARACTERS)
|
||||
1_export.py -ipj common/characters common/characters_maps_hr
|
||||
title Ryzom Core: 2_build.py (CHARACTERS)
|
||||
2_build.py -ipj common/characters common/characters_maps_hr
|
||||
title Ryzom Core: 3_install.py (CHARACTERS)
|
||||
3_install.py -ipj common/characters common/characters_maps_hr
|
||||
title Ryzom Core: b1_client_dev.py (CHARACTERS)
|
||||
b1_client_dev.py
|
||||
title Ryzom Core: b2_shard_data.py (CHARACTERS)
|
||||
b2_shard_data.py
|
||||
title Ryzom Core: Ready (CHARACTERS)
|
11
code/nel/tools/build_gamedata/panoply_dev.bat
Normal file
11
code/nel/tools/build_gamedata/panoply_dev.bat
Normal file
|
@ -0,0 +1,11 @@
|
|||
title Ryzom Core: 1_export.py (PANOPLY)
|
||||
1_export.py -ipj common/characters_maps_hr
|
||||
title Ryzom Core: 2_build.py (PANOPLY)
|
||||
2_build.py -ipj common/characters_maps_hr
|
||||
title Ryzom Core: 3_install.py (PANOPLY)
|
||||
3_install.py -ipj common/characters_maps_hr
|
||||
title Ryzom Core: b1_client_dev.py (PANOPLY)
|
||||
b1_client_dev.py
|
||||
title Ryzom Core: b2_shard_data.py (PANOPLY)
|
||||
b2_shard_data.py
|
||||
title Ryzom Core: Ready (PANOPLY)
|
|
@ -74,6 +74,8 @@ cfgOut.write("{\n")
|
|||
cfgOut.write("\t\"" + ExportBuildDirectory + "/" + ClodExportDirectory + "\", \n")
|
||||
cfgOut.write("\t\"" + ExportBuildDirectory + "/" + SkelExportDirectory + "\", \n")
|
||||
cfgOut.write("\t\"" + ExportBuildDirectory + "/" + AnimBuildDirectory + "\", \n")
|
||||
cfgOut.write("\t\"" + ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory + "\", \n")
|
||||
cfgOut.write("\t\"" + ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory + "\", \n")
|
||||
cfgOut.write("};\n")
|
||||
cfgOut.write("\n")
|
||||
cfgOut.close()
|
||||
|
|
|
@ -225,7 +225,7 @@ void CProgress::internalProgress (float value)
|
|||
|
||||
if (!stereoHMD || StereoDisplay->wantInterface2D())
|
||||
{
|
||||
nldebug("Draw progress 2D");
|
||||
// nldebug("Draw progress 2D");
|
||||
|
||||
// Font factor
|
||||
float fontFactor = 1;
|
||||
|
|
|
@ -237,24 +237,12 @@ void SItemSpecialEffects::serial(class NLMISC::IStream &f)
|
|||
//--------------------------------------------------------------
|
||||
// init()
|
||||
//--------------------------------------------------------------
|
||||
void CStaticItem::init()
|
||||
void CStaticItem::init(bool doDelete)
|
||||
{
|
||||
Family = ITEMFAMILY::UNDEFINED;
|
||||
Type = ITEM_TYPE::UNDEFINED;
|
||||
|
||||
Armor = NULL;
|
||||
MeleeWeapon = NULL;
|
||||
RangeWeapon = NULL;
|
||||
Ammo = NULL;
|
||||
Shield = NULL;
|
||||
TamingTool = NULL;
|
||||
Mp = NULL;
|
||||
GuildOption = NULL;
|
||||
Cosmetics = NULL;
|
||||
ItemServiceData = NULL;
|
||||
ConsumableItem = NULL;
|
||||
XpCatalyser = NULL;
|
||||
CommandTicket = NULL;
|
||||
clearPtrs(doDelete);
|
||||
|
||||
Skill = SKILLS::unknown;
|
||||
MinSkill = 0;
|
||||
|
@ -287,16 +275,54 @@ void CStaticItem::init()
|
|||
RequiredCharacQualityFactor = 0.0f;
|
||||
RequiredCharacQualityOffset = 0;
|
||||
|
||||
ItemSpecialEffects = NULL;
|
||||
} // init //
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
void CStaticItem::clearPtrs(bool doDelete)
|
||||
{
|
||||
if (doDelete)
|
||||
{
|
||||
delete Armor;
|
||||
delete MeleeWeapon;
|
||||
delete RangeWeapon;
|
||||
delete Ammo;
|
||||
delete Shield;
|
||||
delete TamingTool;
|
||||
delete Mp;
|
||||
delete GuildOption;
|
||||
delete Cosmetics;
|
||||
delete ItemServiceData;
|
||||
delete ConsumableItem;
|
||||
delete XpCatalyser;
|
||||
delete CommandTicket;
|
||||
delete ItemSpecialEffects;
|
||||
}
|
||||
|
||||
Armor = NULL;
|
||||
MeleeWeapon = NULL;
|
||||
RangeWeapon = NULL;
|
||||
Ammo = NULL;
|
||||
Shield = NULL;
|
||||
TamingTool = NULL;
|
||||
Mp = NULL;
|
||||
GuildOption = NULL;
|
||||
Cosmetics = NULL;
|
||||
ItemServiceData = NULL;
|
||||
ConsumableItem = NULL;
|
||||
XpCatalyser = NULL;
|
||||
CommandTicket = NULL;
|
||||
ItemSpecialEffects = NULL;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// copy constructor
|
||||
//--------------------------------------------------------------
|
||||
CStaticItem::CStaticItem( const CStaticItem& itm )
|
||||
{
|
||||
clearPtrs(false);
|
||||
|
||||
*this = itm;
|
||||
if(itm.Armor)
|
||||
{
|
||||
|
@ -1443,6 +1469,9 @@ void CStaticItem::readGeorges (const NLMISC::CSmartPtr<NLGEORGES::UForm> &form,
|
|||
if (form == NULL)
|
||||
return;
|
||||
|
||||
// Clear pointers to previous data
|
||||
clearPtrs(true);
|
||||
|
||||
// Get the root node, always exist
|
||||
UFormElm &root = form->getRootNode ();
|
||||
|
||||
|
@ -1993,37 +2022,6 @@ float CStaticItem::getBaseWeight() const
|
|||
}
|
||||
#endif
|
||||
|
||||
// ***************************************************************************
|
||||
void CStaticItem::clearPtrs(bool doDelete)
|
||||
{
|
||||
if(doDelete)
|
||||
{
|
||||
if (Ammo != NULL ) delete Ammo;
|
||||
if (Armor != NULL ) delete Armor;
|
||||
if (MeleeWeapon != NULL ) delete MeleeWeapon;
|
||||
if (RangeWeapon != NULL ) delete RangeWeapon;
|
||||
if (Cosmetics != NULL ) delete Cosmetics;
|
||||
if (Mp != NULL ) delete Mp;
|
||||
if (GuildOption != NULL ) delete GuildOption;
|
||||
if (Shield != NULL ) delete Shield;
|
||||
if (TamingTool != NULL) delete TamingTool;
|
||||
if (ItemServiceData != NULL) delete ItemServiceData;
|
||||
if (CommandTicket != NULL) delete CommandTicket;
|
||||
}
|
||||
|
||||
Ammo = NULL;
|
||||
Armor = NULL;
|
||||
MeleeWeapon = NULL;
|
||||
RangeWeapon = NULL;
|
||||
Cosmetics = NULL;
|
||||
Mp = NULL;
|
||||
GuildOption = NULL;
|
||||
Shield = NULL;
|
||||
TamingTool = NULL;
|
||||
ItemServiceData = NULL;
|
||||
CommandTicket = NULL;
|
||||
}
|
||||
|
||||
|
||||
uint32 CStaticItem::getMaxStackSize() const
|
||||
{
|
||||
|
|
|
@ -812,13 +812,13 @@ public:
|
|||
public:
|
||||
|
||||
/// Constructor
|
||||
CStaticItem() { init(); }
|
||||
CStaticItem() { init(false); }
|
||||
|
||||
/// copy constructor
|
||||
CStaticItem( const CStaticItem& itm );
|
||||
|
||||
/// init method
|
||||
void init();
|
||||
void init(bool doDelete = true);
|
||||
|
||||
/// destructor
|
||||
virtual ~CStaticItem();
|
||||
|
|
|
@ -1784,6 +1784,7 @@ void CScreenshotIslands::buildBackTextureHLS(const std::string & islandName, con
|
|||
|
||||
|
||||
// keep more filled eighth of circle
|
||||
nlassert(!sortedHLS.empty()); // If it crashes here, you may be missing .zonel's.
|
||||
itHLS = sortedHLS.begin();
|
||||
uint h, s, v;
|
||||
RGB2HSV(*itHLS, h, s, v);
|
||||
|
|
|
@ -211,7 +211,7 @@ int main(int argc, char* argv[])
|
|||
catch(const EStream &)
|
||||
{
|
||||
mustRebuild = true; // damaged file or bad version ? -> force rebuild
|
||||
delete packedIsland; // remove whatever was serialized
|
||||
// delete packedIsland; // remove whatever was serialized // NOPE. smart pointer
|
||||
packedIsland = new CPackedWorldHolder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#include "nel3d_widget.h"
|
||||
#include "nel/3d/u_driver.h"
|
||||
#include "nel/3d/text_context.h"
|
||||
|
@ -29,7 +28,7 @@
|
|||
#include <QResizeEvent>
|
||||
|
||||
Nel3DWidget::Nel3DWidget( QWidget *parent ) :
|
||||
QWidget( parent )
|
||||
NEL3DWIDGET( parent )
|
||||
{
|
||||
driver = NULL;
|
||||
textContext = NULL;
|
||||
|
|
|
@ -18,10 +18,22 @@
|
|||
#ifndef NEL3D_WIDGET_H
|
||||
#define NEL3D_WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "nel/misc/types_nl.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef NEL3DWIDGET
|
||||
#undef NEL3DWIDGET
|
||||
#endif
|
||||
|
||||
#ifdef NL_OS_WINDOWS
|
||||
#include <QWidget>
|
||||
#define NEL3DWIDGET QWidget
|
||||
#else
|
||||
#include <QGLWidget>
|
||||
#define NEL3DWIDGET QGLWidget
|
||||
#endif
|
||||
|
||||
|
||||
#include "../core_global.h"
|
||||
|
||||
namespace NL3D
|
||||
|
@ -31,7 +43,7 @@ namespace NL3D
|
|||
}
|
||||
|
||||
/// Nel 3D interface to Qt
|
||||
class CORE_EXPORT Nel3DWidget : public QWidget
|
||||
class CORE_EXPORT Nel3DWidget : public NEL3DWIDGET
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -143,6 +143,8 @@ void ContextManager::currentTabChanged(int index)
|
|||
if (index >= 0)
|
||||
{
|
||||
IContext *context = d->m_contexts.at(index);
|
||||
context->onActivated();
|
||||
|
||||
Q_EMIT currentContextChanged(context);
|
||||
}
|
||||
}
|
||||
|
@ -158,4 +160,4 @@ int ContextManager::indexOf(const QString &id) const
|
|||
return -1;
|
||||
}
|
||||
|
||||
} /* namespace Core */
|
||||
} /* namespace Core */
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
virtual void newDocument(){}
|
||||
|
||||
virtual void close(){}
|
||||
|
||||
virtual void onActivated(){}
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
|
|
@ -108,8 +108,14 @@ void MainWindow::extensionsInitialized()
|
|||
readSettings();
|
||||
connect(m_contextManager, SIGNAL(currentContextChanged(Core::IContext *)),
|
||||
this, SLOT(updateContext(Core::IContext *)));
|
||||
if (m_contextManager->currentContext() != NULL)
|
||||
updateContext(m_contextManager->currentContext());
|
||||
|
||||
Core::IContext *context = m_contextManager->currentContext();
|
||||
if (context != NULL)
|
||||
{
|
||||
updateContext(context);
|
||||
context->onActivated();
|
||||
}
|
||||
|
||||
show();
|
||||
}
|
||||
|
||||
|
|
|
@ -176,6 +176,9 @@ void ExpressionEditor::onDeleteSelection()
|
|||
}
|
||||
}
|
||||
|
||||
if( item == m_pvt->m_root )
|
||||
m_pvt->m_root = NULL;
|
||||
|
||||
m_scene->removeItem( item );
|
||||
delete item;
|
||||
}
|
||||
|
|
|
@ -297,9 +297,16 @@ QString ExpressionNode::build() const
|
|||
|
||||
QStringList l = m_name.split( ' ' );
|
||||
result = l[ 0 ];
|
||||
result += "( ";
|
||||
|
||||
int c = m_links.count();
|
||||
if( c == 1 )
|
||||
{
|
||||
result += "()";
|
||||
return result;
|
||||
}
|
||||
|
||||
result += "( ";
|
||||
|
||||
for( int i = 1; i < c; i++ )
|
||||
{
|
||||
ExpressionLink *link = m_links[ i ];
|
||||
|
|
8
code/studio/src/plugins/gui_editor/expressions/abs.xml
Normal file
8
code/studio/src/plugins/gui_editor/expressions/abs.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>abs</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/band.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/band.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>band</name>
|
||||
<variable>true</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
8
code/studio/src/plugins/gui_editor/expressions/bnot.xml
Normal file
8
code/studio/src/plugins/gui_editor/expressions/bnot.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>bnot</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/bor.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/bor.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>bor</name>
|
||||
<variable>true</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/bxor.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/bxor.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>bxor</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Database</category>
|
||||
<name>dbcount</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Logical</category>
|
||||
<name>depends</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>extSign11To64</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>extSign8To64</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Color</category>
|
||||
<name>getAlpha</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Color</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Color</category>
|
||||
<name>getBlue</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Color</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Color</category>
|
||||
<name>getGreen</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Color</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Color</category>
|
||||
<name>getRed</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Color</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>getbit</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Integer</slot>
|
||||
<slot>Bit</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Database</category>
|
||||
<name>getprop</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>property</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>identity</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
10
code/studio/src/plugins/gui_editor/expressions/ilinear.xml
Normal file
10
code/studio/src/plugins/gui_editor/expressions/ilinear.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>ilinear</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Interpolant</slot>
|
||||
<slot>Start</slot>
|
||||
<slot>End</slot>
|
||||
</slots>
|
||||
</expression>
|
8
code/studio/src/plugins/gui_editor/expressions/int.xml
Normal file
8
code/studio/src/plugins/gui_editor/expressions/int.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>int</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Color</category>
|
||||
<name>intToColor</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>Integer</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,5 @@
|
|||
<expression>
|
||||
<category>Nel</category>
|
||||
<name>isFinalVersion</name>
|
||||
<variable>false</variable>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Localization</category>
|
||||
<name>localize</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>String</slot>
|
||||
</slots>
|
||||
</expression>
|
11
code/studio/src/plugins/gui_editor/expressions/makeRGB.xml
Normal file
11
code/studio/src/plugins/gui_editor/expressions/makeRGB.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<expression>
|
||||
<category>Color</category>
|
||||
<name>makeRGB</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>R</slot>
|
||||
<slot>G</slot>
|
||||
<slot>B</slot>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/max.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/max.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>max</name>
|
||||
<variable>true</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/min.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/min.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>min</name>
|
||||
<variable>true</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/mod.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/mod.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>mod</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Database</category>
|
||||
<name>oldvalue</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>property</slot>
|
||||
</slots>
|
||||
</expression>
|
5
code/studio/src/plugins/gui_editor/expressions/rand.xml
Normal file
5
code/studio/src/plugins/gui_editor/expressions/rand.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<expression>
|
||||
<category>Mathematical</category>
|
||||
<name>rand</name>
|
||||
<variable>false</variable>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/sal.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/sal.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>sal</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/sar.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/sar.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>sar</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Time</category>
|
||||
<name>secondsToTimeString</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -0,0 +1,8 @@
|
|||
<expression>
|
||||
<category>Time</category>
|
||||
<name>secondsToTimeStringShort</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/shl.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/shl.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>shl</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/shr.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/shr.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>Bits</category>
|
||||
<name>shr</name>
|
||||
<variable>false</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
9
code/studio/src/plugins/gui_editor/expressions/str.xml
Normal file
9
code/studio/src/plugins/gui_editor/expressions/str.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<expression>
|
||||
<category>String</category>
|
||||
<name>str</name>
|
||||
<variable>true</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
</slots>
|
||||
</expression>
|
10
code/studio/src/plugins/gui_editor/expressions/switch.xml
Normal file
10
code/studio/src/plugins/gui_editor/expressions/switch.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<expression>
|
||||
<category>Logical</category>
|
||||
<name>switch</name>
|
||||
<variable>true</variable>
|
||||
<slots>
|
||||
<slot>A</slot>
|
||||
<slot>B</slot>
|
||||
<slot>C</slot>
|
||||
</slots>
|
||||
</expression>
|
|
@ -484,6 +484,11 @@ void MissionCompilerMainWindow::saveConfig() {
|
|||
settings->sync();
|
||||
}
|
||||
|
||||
void MissionCompilerMainWindow::onActivated()
|
||||
{
|
||||
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig;
|
||||
}
|
||||
|
||||
void MissionCompilerMainWindow::handleChangedSettings()
|
||||
{
|
||||
QStringList servers;
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
void saveConfig();
|
||||
QUndoStack *getUndoStack() { return m_undoStack; }
|
||||
|
||||
void onActivated();
|
||||
|
||||
typedef std::map<std::string, CMission> TMissionContainer;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
|
|
@ -83,6 +83,12 @@ public:
|
|||
virtual void open() {}
|
||||
|
||||
|
||||
void onActivated()
|
||||
{
|
||||
m_missionCompilerMainWindow->onActivated();
|
||||
}
|
||||
|
||||
|
||||
MissionCompilerMainWindow *m_missionCompilerMainWindow;
|
||||
};
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ void CObjectViewer::init( NL3D::UDriver *driver )
|
|||
|
||||
NL3D::CBloomEffect::instance().setDriver(_Driver);
|
||||
NL3D::CBloomEffect::instance().setScene(_Scene);
|
||||
NL3D::CBloomEffect::instance().init(!_Direct3D);
|
||||
NL3D::CBloomEffect::instance().init();
|
||||
NL3D::CBloomEffect::instance().setDensityBloom(uint8(_BloomDensity));
|
||||
NL3D::CBloomEffect::instance().setSquareBloom(_BloomSquare);
|
||||
|
||||
|
@ -172,7 +172,7 @@ void CObjectViewer::renderDriver()
|
|||
// Render the scene.
|
||||
if((NL3D::CBloomEffect::instance().getDriver() != 0) && (_BloomEffect))
|
||||
{
|
||||
NL3D::CBloomEffect::instance().initBloom();
|
||||
NL3D::CBloomEffect::instance().init();
|
||||
}
|
||||
_Driver->clearBuffers(_BackgroundColor);
|
||||
}
|
||||
|
@ -184,8 +184,7 @@ void CObjectViewer::renderScene()
|
|||
|
||||
if((NL3D::CBloomEffect::instance().getDriver() != 0) && (_BloomEffect))
|
||||
{
|
||||
NL3D::CBloomEffect::instance().endBloom();
|
||||
NL3D::CBloomEffect::instance().endInterfacesDisplayBloom();
|
||||
NL3D::CBloomEffect::instance().applyBloom();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,36 +54,6 @@ bool WorldEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManage
|
|||
|
||||
WorldEditorSettingsPage *weSettings = new WorldEditorSettingsPage(this);
|
||||
addAutoReleasedObject(weSettings);
|
||||
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
settings->beginGroup(Constants::WORLD_EDITOR_SECTION);
|
||||
m_ligoConfig.CellSize = settings->value(Constants::WORLD_EDITOR_CELL_SIZE, "160").toFloat();
|
||||
m_ligoConfig.Snap = settings->value(Constants::WORLD_EDITOR_SNAP, "1").toFloat();
|
||||
m_ligoConfig.ZoneSnapShotRes = settings->value(Constants::ZONE_SNAPSHOT_RES, "128").toUInt();
|
||||
QString fileName = settings->value(Constants::PRIMITIVE_CLASS_FILENAME, "world_editor_classes.xml").toString();
|
||||
settings->endGroup();
|
||||
try
|
||||
{
|
||||
// Search path of file world_editor_classes.xml
|
||||
std::string ligoPath = NLMISC::CPath::lookup(fileName.toUtf8().constData());
|
||||
// Init LIGO
|
||||
m_ligoConfig.readPrimitiveClass(ligoPath.c_str(), true);
|
||||
NLLIGO::Register();
|
||||
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig;
|
||||
}
|
||||
catch (NLMISC::Exception &e)
|
||||
{
|
||||
*errorString = tr("(%1)").arg(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset
|
||||
m_ligoConfig.resetPrimitiveConfiguration ();
|
||||
|
||||
// TODO: get file names! from settings
|
||||
m_ligoConfig.readPrimitiveClass("world_editor_primitive_configuration.xml", true);
|
||||
|
||||
|
||||
addAutoReleasedObject(new WorldEditorContext(this));
|
||||
return true;
|
||||
}
|
||||
|
@ -116,6 +86,33 @@ WorldEditorContext::WorldEditorContext(QObject *parent)
|
|||
: IContext(parent),
|
||||
m_worldEditorWindow(0)
|
||||
{
|
||||
QSettings *settings = Core::ICore::instance()->settings();
|
||||
settings->beginGroup(Constants::WORLD_EDITOR_SECTION);
|
||||
m_ligoConfig.CellSize = settings->value(Constants::WORLD_EDITOR_CELL_SIZE, "160").toFloat();
|
||||
m_ligoConfig.Snap = settings->value(Constants::WORLD_EDITOR_SNAP, "1").toFloat();
|
||||
m_ligoConfig.ZoneSnapShotRes = settings->value(Constants::ZONE_SNAPSHOT_RES, "128").toUInt();
|
||||
QString fileName = settings->value(Constants::PRIMITIVE_CLASS_FILENAME, "world_editor_classes.xml").toString();
|
||||
settings->endGroup();
|
||||
try
|
||||
{
|
||||
// Search path of file world_editor_classes.xml
|
||||
std::string ligoPath = NLMISC::CPath::lookup(fileName.toUtf8().constData());
|
||||
// Init LIGO
|
||||
m_ligoConfig.readPrimitiveClass(ligoPath.c_str(), true);
|
||||
NLLIGO::Register();
|
||||
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig;
|
||||
}
|
||||
catch (NLMISC::Exception &e)
|
||||
{
|
||||
nlinfo( "Error starting LIGO." );
|
||||
}
|
||||
|
||||
// Reset
|
||||
m_ligoConfig.resetPrimitiveConfiguration ();
|
||||
|
||||
// TODO: get file names! from settings
|
||||
m_ligoConfig.readPrimitiveClass("world_editor_primitive_configuration.xml", true);
|
||||
|
||||
m_worldEditorWindow = new WorldEditorWindow();
|
||||
}
|
||||
|
||||
|
@ -124,6 +121,11 @@ QUndoStack *WorldEditorContext::undoStack()
|
|||
return m_worldEditorWindow->undoStack();
|
||||
}
|
||||
|
||||
void WorldEditorContext::onActivated()
|
||||
{
|
||||
NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig;
|
||||
}
|
||||
|
||||
void WorldEditorContext::open()
|
||||
{
|
||||
m_worldEditorWindow->open();
|
||||
|
@ -136,4 +138,4 @@ QWidget *WorldEditorContext::widget()
|
|||
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN(WorldEditor::WorldEditorPlugin)
|
||||
Q_EXPORT_PLUGIN(WorldEditor::WorldEditorPlugin)
|
||||
|
|
|
@ -59,7 +59,6 @@ protected:
|
|||
NLMISC::CLibraryContext *m_libContext;
|
||||
|
||||
private:
|
||||
NLLIGO::CLigoConfig m_ligoConfig;
|
||||
ExtensionSystem::IPluginManager *m_plugMan;
|
||||
QList<QObject *> m_autoReleaseObjects;
|
||||
};
|
||||
|
@ -88,9 +87,14 @@ public:
|
|||
|
||||
virtual QUndoStack *undoStack();
|
||||
|
||||
void onActivated();
|
||||
|
||||
virtual QWidget *widget();
|
||||
|
||||
WorldEditorWindow *m_worldEditorWindow;
|
||||
|
||||
private:
|
||||
NLLIGO::CLigoConfig m_ligoConfig;
|
||||
};
|
||||
|
||||
} // namespace WorldEditor
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
~WorldEditorWindow();
|
||||
|
||||
QUndoStack *undoStack() const;
|
||||
void onActivated();
|
||||
void maybeSave();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
Loading…
Reference in a new issue