mirror of
https://github.com/minetest/minetest.git
synced 2024-08-20 13:34:17 +02:00
Compare commits
No commits in common. "a15e0d09cdb8f9e126e750ceb6c411392dd36055" and "f287364b7bf3fa4edf4520acecf43d26a19864f5" have entirely different histories.
a15e0d09cd
...
f287364b7b
@ -3902,7 +3902,6 @@ Operators
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
Operators can be used if all of the involved vectors have metatables:
|
Operators can be used if all of the involved vectors have metatables:
|
||||||
|
|
||||||
* `v1 == v2`:
|
* `v1 == v2`:
|
||||||
* Returns whether `v1` and `v2` are identical.
|
* Returns whether `v1` and `v2` are identical.
|
||||||
* `-v`:
|
* `-v`:
|
||||||
|
@ -200,7 +200,7 @@ public:
|
|||||||
\param loop: True if the animation should loop, false if not
|
\param loop: True if the animation should loop, false if not
|
||||||
\param scale: True if the sprite should scale to button size, false if not */
|
\param scale: True if the sprite should scale to button size, false if not */
|
||||||
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||||
video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false) = 0;
|
video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false, bool scale = false) = 0;
|
||||||
|
|
||||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const = 0;
|
virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const = 0;
|
||||||
@ -211,6 +211,9 @@ public:
|
|||||||
//! Returns if the sprite in the given state does loop
|
//! Returns if the sprite in the given state does loop
|
||||||
virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const = 0;
|
virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const = 0;
|
||||||
|
|
||||||
|
//! Returns if the sprite in the given state is scaled
|
||||||
|
virtual bool getSpriteScale(EGUI_BUTTON_STATE state) const = 0;
|
||||||
|
|
||||||
//! Sets if the button should behave like a push button.
|
//! Sets if the button should behave like a push button.
|
||||||
/** Which means it can be in two states: Normal or Pressed. With a click on the button,
|
/** Which means it can be in two states: Normal or Pressed. With a click on the button,
|
||||||
the user can change the state of the button. */
|
the user can change the state of the button. */
|
||||||
|
@ -374,12 +374,6 @@ const c8 *const GUISkinFontNames[EGDF_COUNT + 1] = {
|
|||||||
class IGUISkin : virtual public IReferenceCounted
|
class IGUISkin : virtual public IReferenceCounted
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! returns display density scaling factor
|
|
||||||
virtual float getScale() const = 0;
|
|
||||||
|
|
||||||
//! sets display density scaling factor
|
|
||||||
virtual void setScale(float scale) = 0;
|
|
||||||
|
|
||||||
//! returns default color
|
//! returns default color
|
||||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0;
|
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0;
|
||||||
|
|
||||||
|
@ -75,11 +75,12 @@ void CGUIButton::setSpriteBank(IGUISpriteBank *sprites)
|
|||||||
SpriteBank = sprites;
|
SpriteBank = sprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
|
void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
|
||||||
{
|
{
|
||||||
ButtonSprites[(u32)state].Index = index;
|
ButtonSprites[(u32)state].Index = index;
|
||||||
ButtonSprites[(u32)state].Color = color;
|
ButtonSprites[(u32)state].Color = color;
|
||||||
ButtonSprites[(u32)state].Loop = loop;
|
ButtonSprites[(u32)state].Loop = loop;
|
||||||
|
ButtonSprites[(u32)state].Scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
@ -100,6 +101,12 @@ bool CGUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
|
|||||||
return ButtonSprites[(u32)state].Loop;
|
return ButtonSprites[(u32)state].Loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Returns if the sprite in the given state is scaled
|
||||||
|
bool CGUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
|
||||||
|
{
|
||||||
|
return ButtonSprites[(u32)state].Scale;
|
||||||
|
}
|
||||||
|
|
||||||
//! called if an event happened.
|
//! called if an event happened.
|
||||||
bool CGUIButton::OnEvent(const SEvent &event)
|
bool CGUIButton::OnEvent(const SEvent &event)
|
||||||
{
|
{
|
||||||
@ -287,26 +294,19 @@ void CGUIButton::draw()
|
|||||||
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di ¢er)
|
void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di ¢er)
|
||||||
{
|
{
|
||||||
u32 stateIdx = (u32)state;
|
u32 stateIdx = (u32)state;
|
||||||
s32 spriteIdx = ButtonSprites[stateIdx].Index;
|
|
||||||
if (spriteIdx == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
|
if (ButtonSprites[stateIdx].Index != -1) {
|
||||||
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
|
if (ButtonSprites[stateIdx].Scale) {
|
||||||
|
const video::SColor colors[] = {ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color};
|
||||||
IGUISkin *skin = Environment->getSkin();
|
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect,
|
||||||
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
|
&AbsoluteClippingRect, colors,
|
||||||
core::rect<s32> rect(center, srcRect.getSize() * scale);
|
|
||||||
rect -= rect.getSize() / 2;
|
|
||||||
|
|
||||||
const video::SColor colors[] = {
|
|
||||||
ButtonSprites[stateIdx].Color,
|
|
||||||
ButtonSprites[stateIdx].Color,
|
|
||||||
ButtonSprites[stateIdx].Color,
|
|
||||||
ButtonSprites[stateIdx].Color,
|
|
||||||
};
|
|
||||||
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
|
|
||||||
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
|
os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop);
|
||||||
|
} else {
|
||||||
|
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
||||||
|
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(),
|
||||||
|
ButtonSprites[stateIdx].Loop, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
|
EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
virtual void setSprite(EGUI_BUTTON_STATE state, s32 index,
|
||||||
video::SColor color = video::SColor(255, 255, 255, 255),
|
video::SColor color = video::SColor(255, 255, 255, 255),
|
||||||
bool loop = false) override;
|
bool loop = false, bool scale = false) override;
|
||||||
|
|
||||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
|
s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override;
|
||||||
@ -103,6 +103,9 @@ public:
|
|||||||
//! Returns if the sprite in the given state does loop
|
//! Returns if the sprite in the given state does loop
|
||||||
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
|
bool getSpriteLoop(EGUI_BUTTON_STATE state) const override;
|
||||||
|
|
||||||
|
//! Returns if the sprite in the given state is scaled
|
||||||
|
bool getSpriteScale(EGUI_BUTTON_STATE state) const override;
|
||||||
|
|
||||||
//! Sets if the button should behave like a push button. Which means it
|
//! Sets if the button should behave like a push button. Which means it
|
||||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||||
//! the user can change the state of the button.
|
//! the user can change the state of the button.
|
||||||
@ -155,18 +158,19 @@ private:
|
|||||||
struct ButtonSprite
|
struct ButtonSprite
|
||||||
{
|
{
|
||||||
ButtonSprite() :
|
ButtonSprite() :
|
||||||
Index(-1), Loop(false)
|
Index(-1), Loop(false), Scale(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const ButtonSprite &other) const
|
bool operator==(const ButtonSprite &other) const
|
||||||
{
|
{
|
||||||
return Index == other.Index && Color == other.Color && Loop == other.Loop;
|
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Index;
|
s32 Index;
|
||||||
video::SColor Color;
|
video::SColor Color;
|
||||||
bool Loop;
|
bool Loop;
|
||||||
|
bool Scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonSprite ButtonSprites[EGBS_COUNT];
|
ButtonSprite ButtonSprites[EGBS_COUNT];
|
||||||
|
@ -24,12 +24,6 @@ public:
|
|||||||
//! destructor
|
//! destructor
|
||||||
virtual ~CGUISkin();
|
virtual ~CGUISkin();
|
||||||
|
|
||||||
//! returns display density scaling factor
|
|
||||||
virtual float getScale() const override { return Scale; }
|
|
||||||
|
|
||||||
//! sets display density scaling factor
|
|
||||||
virtual void setScale(float scale) override { Scale = scale; }
|
|
||||||
|
|
||||||
//! returns default color
|
//! returns default color
|
||||||
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
|
video::SColor getColor(EGUI_DEFAULT_COLOR color) const override;
|
||||||
|
|
||||||
@ -216,7 +210,6 @@ public:
|
|||||||
EGUI_SKIN_TYPE getType() const override;
|
EGUI_SKIN_TYPE getType() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float Scale = 1.0f;
|
|
||||||
video::SColor Colors[EGDC_COUNT];
|
video::SColor Colors[EGDC_COUNT];
|
||||||
s32 Sizes[EGDS_COUNT];
|
s32 Sizes[EGDS_COUNT];
|
||||||
u32 Icons[EGDI_COUNT];
|
u32 Icons[EGDI_COUNT];
|
||||||
|
@ -129,9 +129,9 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE irrlichtKey)
|
bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key)
|
||||||
{
|
{
|
||||||
switch (irrlichtKey) {
|
switch (key) {
|
||||||
// keys which are known to have safe special character interpretation
|
// keys which are known to have safe special character interpretation
|
||||||
// could need changes over time (removals and additions!)
|
// could need changes over time (removals and additions!)
|
||||||
case KEY_RETURN:
|
case KEY_RETURN:
|
||||||
@ -189,68 +189,24 @@ bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE irrlichtKey)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock)
|
int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key)
|
||||||
{
|
{
|
||||||
switch (irrlichtKey) {
|
|
||||||
// special cases that always return a char regardless of how the SDL keycode
|
// special cases that always return a char regardless of how the SDL keycode
|
||||||
// looks
|
// looks
|
||||||
|
switch (key) {
|
||||||
case KEY_RETURN:
|
case KEY_RETURN:
|
||||||
case KEY_ESCAPE:
|
case KEY_ESCAPE:
|
||||||
return (int)irrlichtKey;
|
return (int)key;
|
||||||
|
|
||||||
// This is necessary for keys on the numpad because they don't use the same
|
|
||||||
// keycodes as their non-numpad versions (whose keycodes correspond to chars),
|
|
||||||
// but have their own SDL keycodes and their own Irrlicht keycodes (which
|
|
||||||
// don't correspond to chars).
|
|
||||||
case KEY_MULTIPLY:
|
|
||||||
return '*';
|
|
||||||
case KEY_ADD:
|
|
||||||
return '+';
|
|
||||||
case KEY_SUBTRACT:
|
|
||||||
return '-';
|
|
||||||
case KEY_DIVIDE:
|
|
||||||
return '/';
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numlock) {
|
|
||||||
// Number keys on the numpad are also affected, but we only want them
|
|
||||||
// to produce number chars when numlock is enabled.
|
|
||||||
switch (irrlichtKey) {
|
|
||||||
case KEY_NUMPAD0:
|
|
||||||
return '0';
|
|
||||||
case KEY_NUMPAD1:
|
|
||||||
return '1';
|
|
||||||
case KEY_NUMPAD2:
|
|
||||||
return '2';
|
|
||||||
case KEY_NUMPAD3:
|
|
||||||
return '3';
|
|
||||||
case KEY_NUMPAD4:
|
|
||||||
return '4';
|
|
||||||
case KEY_NUMPAD5:
|
|
||||||
return '5';
|
|
||||||
case KEY_NUMPAD6:
|
|
||||||
return '6';
|
|
||||||
case KEY_NUMPAD7:
|
|
||||||
return '7';
|
|
||||||
case KEY_NUMPAD8:
|
|
||||||
return '8';
|
|
||||||
case KEY_NUMPAD9:
|
|
||||||
return '9';
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SDL in-place ORs values with no character representation with 1<<30
|
// SDL in-place ORs values with no character representation with 1<<30
|
||||||
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
// https://wiki.libsdl.org/SDL2/SDLKeycodeLookup
|
||||||
// This also affects the numpad keys btw.
|
if (assumedChar & (1 << 30))
|
||||||
if (sdlKey & (1 << 30))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
switch (irrlichtKey) {
|
switch (key) {
|
||||||
case KEY_PRIOR:
|
case KEY_PRIOR:
|
||||||
case KEY_NEXT:
|
case KEY_NEXT:
|
||||||
case KEY_HOME:
|
case KEY_HOME:
|
||||||
@ -262,7 +218,7 @@ int CIrrDeviceSDL::findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtK
|
|||||||
case KEY_NUMLOCK:
|
case KEY_NUMLOCK:
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
return sdlKey;
|
return assumedChar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,7 +656,7 @@ bool CIrrDeviceSDL::run()
|
|||||||
{
|
{
|
||||||
os::Timer::tick();
|
os::Timer::tick();
|
||||||
|
|
||||||
SEvent irrevent{};
|
SEvent irrevent;
|
||||||
SDL_Event SDL_event;
|
SDL_Event SDL_event;
|
||||||
|
|
||||||
while (!Close && wrap_PollEvent(&SDL_event)) {
|
while (!Close && wrap_PollEvent(&SDL_event)) {
|
||||||
@ -869,8 +825,7 @@ bool CIrrDeviceSDL::run()
|
|||||||
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN);
|
||||||
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0;
|
||||||
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
|
irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL) != 0;
|
||||||
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key,
|
irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key);
|
||||||
(SDL_event.key.keysym.mod & KMOD_NUM) != 0);
|
|
||||||
postEventFromUser(irrevent);
|
postEventFromUser(irrevent);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -273,10 +273,10 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
// Check if a key is a known special character with no side effects on text boxes.
|
// Check if a key is a known special character with no side effects on text boxes.
|
||||||
static bool keyIsKnownSpecial(EKEY_CODE irrlichtKey);
|
static bool keyIsKnownSpecial(EKEY_CODE key);
|
||||||
|
|
||||||
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
|
// Return the Char that should be sent to Irrlicht for the given key (either the one passed in or 0).
|
||||||
static int findCharToPassToIrrlicht(uint32_t sdlKey, EKEY_CODE irrlichtKey, bool numlock);
|
static int findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key);
|
||||||
|
|
||||||
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
// Check if a text box is in focus. Enable or disable SDL_TEXTINPUT events only if in focus.
|
||||||
void resetReceiveTextInputEvents();
|
void resetReceiveTextInputEvents();
|
||||||
|
@ -417,6 +417,7 @@ set(common_SRCS
|
|||||||
light.cpp
|
light.cpp
|
||||||
lighting.cpp
|
lighting.cpp
|
||||||
log.cpp
|
log.cpp
|
||||||
|
#log_types.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
map.cpp
|
map.cpp
|
||||||
map_settings_manager.cpp
|
map_settings_manager.cpp
|
||||||
|
@ -353,7 +353,6 @@ void ClientLauncher::config_guienv()
|
|||||||
|
|
||||||
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
|
float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) *
|
||||||
RenderingEngine::getDisplayDensity();
|
RenderingEngine::getDisplayDensity();
|
||||||
skin->setScale(density);
|
|
||||||
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density));
|
skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density));
|
||||||
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density));
|
skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density));
|
||||||
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
|
skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density));
|
||||||
|
96
src/fm_porting.h
Normal file
96
src/fm_porting.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "porting.h"
|
||||||
|
|
||||||
|
#if defined(linux) || defined(__linux)
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <pthread_np.h>
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
#include <pthread.h>
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(linux) || defined(__linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
#define PORTING_USE_PTHREAD 1
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace porting
|
||||||
|
{
|
||||||
|
|
||||||
|
extern std::atomic_bool g_sighup, g_siginfo;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(linux) || defined(__linux)
|
||||||
|
inline void setThreadName(const char *name) {
|
||||||
|
/* It would be cleaner to do this with pthread_setname_np,
|
||||||
|
* which was added to glibc in version 2.12, but some major
|
||||||
|
* distributions are still runing 2.11 and previous versions.
|
||||||
|
*/
|
||||||
|
prctl(PR_SET_NAME, name);
|
||||||
|
}
|
||||||
|
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||||
|
inline void setThreadName(const char *name) {
|
||||||
|
pthread_set_name_np(pthread_self(), name);
|
||||||
|
}
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
inline void setThreadName(const char *name) {
|
||||||
|
pthread_setname_np(pthread_self(), name);
|
||||||
|
}
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
typedef struct tagTHREADNAME_INFO {
|
||||||
|
DWORD dwType; // must be 0x1000
|
||||||
|
LPCSTR szName; // pointer to name (in user addr space)
|
||||||
|
DWORD dwThreadID; // thread ID (-1=caller thread)
|
||||||
|
DWORD dwFlags; // reserved for future use, must be zero
|
||||||
|
} THREADNAME_INFO;
|
||||||
|
|
||||||
|
inline void setThreadName(const char *name) {
|
||||||
|
THREADNAME_INFO info;
|
||||||
|
info.dwType = 0x1000;
|
||||||
|
info.szName = name;
|
||||||
|
info.dwThreadID = -1;
|
||||||
|
info.dwFlags = 0;
|
||||||
|
__try {
|
||||||
|
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *) &info);
|
||||||
|
} __except (EXCEPTION_CONTINUE_EXECUTION) {}
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
inline void setThreadName(const char *name) {
|
||||||
|
pthread_setname_np(name);
|
||||||
|
}
|
||||||
|
#elif defined(_WIN32) || defined(__GNU__)
|
||||||
|
inline void setThreadName(const char* name) {}
|
||||||
|
#else
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
#warning "Unrecognized platform, thread names will not be available."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void setThreadName(const char* name) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void setThreadPriority(int priority) {
|
||||||
|
#if PORTING_USE_PTHREAD
|
||||||
|
// http://en.cppreference.com/w/cpp/thread/thread/native_handle
|
||||||
|
sched_param sch;
|
||||||
|
//int policy;
|
||||||
|
//pthread_getschedparam(pthread_self(), &policy, &sch);
|
||||||
|
sch.sched_priority = priority;
|
||||||
|
if(pthread_setschedparam(pthread_self(), SCHED_FIFO /*SCHED_RR*/, &sch)) {
|
||||||
|
//std::cout << "Failed to setschedparam: " << std::strerror(errno) << '\n';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SERVER
|
||||||
|
|
||||||
|
//void irr_device_wait_egl (irr::IrrlichtDevice * device = nullptr);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -89,11 +89,12 @@ void GUIButton::setSpriteBank(IGUISpriteBank* sprites)
|
|||||||
SpriteBank = sprites;
|
SpriteBank = sprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop)
|
void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale)
|
||||||
{
|
{
|
||||||
ButtonSprites[(u32)state].Index = index;
|
ButtonSprites[(u32)state].Index = index;
|
||||||
ButtonSprites[(u32)state].Color = color;
|
ButtonSprites[(u32)state].Color = color;
|
||||||
ButtonSprites[(u32)state].Loop = loop;
|
ButtonSprites[(u32)state].Loop = loop;
|
||||||
|
ButtonSprites[(u32)state].Scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
@ -114,6 +115,12 @@ bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const
|
|||||||
return ButtonSprites[(u32)state].Loop;
|
return ButtonSprites[(u32)state].Loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Returns if the sprite in the given state is scaled
|
||||||
|
bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const
|
||||||
|
{
|
||||||
|
return ButtonSprites[(u32)state].Scale;
|
||||||
|
}
|
||||||
|
|
||||||
//! called if an event happened.
|
//! called if an event happened.
|
||||||
bool GUIButton::OnEvent(const SEvent& event)
|
bool GUIButton::OnEvent(const SEvent& event)
|
||||||
{
|
{
|
||||||
@ -347,26 +354,23 @@ void GUIButton::draw()
|
|||||||
void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
|
void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center)
|
||||||
{
|
{
|
||||||
u32 stateIdx = (u32)state;
|
u32 stateIdx = (u32)state;
|
||||||
s32 spriteIdx = ButtonSprites[stateIdx].Index;
|
|
||||||
if (spriteIdx == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber;
|
if (ButtonSprites[stateIdx].Index != -1)
|
||||||
core::rect<s32> srcRect = SpriteBank->getPositions()[rectIdx];
|
{
|
||||||
|
if ( ButtonSprites[stateIdx].Scale )
|
||||||
IGUISkin *skin = Environment->getSkin();
|
{
|
||||||
s32 scale = std::max(std::floor(skin->getScale()), 1.0f);
|
const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color};
|
||||||
core::rect<s32> rect(center, srcRect.getSize() * scale);
|
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner,
|
||||||
rect -= rect.getSize() / 2;
|
&AbsoluteClippingRect, colors[0], // FIXME: remove [0]
|
||||||
|
porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop);
|
||||||
const video::SColor colors[] = {
|
}
|
||||||
ButtonSprites[stateIdx].Color,
|
else
|
||||||
ButtonSprites[stateIdx].Color,
|
{
|
||||||
ButtonSprites[stateIdx].Color,
|
SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center,
|
||||||
ButtonSprites[stateIdx].Color,
|
&AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(),
|
||||||
};
|
ButtonSprites[stateIdx].Loop, true);
|
||||||
SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors,
|
}
|
||||||
porting::getTimeMs() - startTime, ButtonSprites[stateIdx].Loop);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const
|
EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
|
virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index,
|
||||||
video::SColor color=video::SColor(255,255,255,255),
|
video::SColor color=video::SColor(255,255,255,255),
|
||||||
bool loop=false) override;
|
bool loop=false, bool scale=false) override;
|
||||||
|
|
||||||
//! Get the sprite-index for the given state or -1 when no sprite is set
|
//! Get the sprite-index for the given state or -1 when no sprite is set
|
||||||
virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const override;
|
virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const override;
|
||||||
@ -103,6 +103,9 @@ public:
|
|||||||
//! Returns if the sprite in the given state does loop
|
//! Returns if the sprite in the given state does loop
|
||||||
virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override;
|
virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override;
|
||||||
|
|
||||||
|
//! Returns if the sprite in the given state is scaled
|
||||||
|
virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const override;
|
||||||
|
|
||||||
//! Sets if the button should behave like a push button. Which means it
|
//! Sets if the button should behave like a push button. Which means it
|
||||||
//! can be in two states: Normal or Pressed. With a click on the button,
|
//! can be in two states: Normal or Pressed. With a click on the button,
|
||||||
//! the user can change the state of the button.
|
//! the user can change the state of the button.
|
||||||
@ -227,12 +230,13 @@ private:
|
|||||||
{
|
{
|
||||||
bool operator==(const ButtonSprite &other) const
|
bool operator==(const ButtonSprite &other) const
|
||||||
{
|
{
|
||||||
return Index == other.Index && Color == other.Color && Loop == other.Loop;
|
return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Index = -1;
|
s32 Index = -1;
|
||||||
video::SColor Color;
|
video::SColor Color;
|
||||||
bool Loop = false;
|
bool Loop = false;
|
||||||
|
bool Scale = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonSprite ButtonSprites[gui::EGBS_COUNT];
|
ButtonSprite ButtonSprites[gui::EGBS_COUNT];
|
||||||
|
@ -27,12 +27,6 @@ namespace gui
|
|||||||
//! destructor
|
//! destructor
|
||||||
virtual ~GUISkin();
|
virtual ~GUISkin();
|
||||||
|
|
||||||
//! returns display density scaling factor
|
|
||||||
virtual float getScale() const { return Scale; }
|
|
||||||
|
|
||||||
//! sets display density scaling factor
|
|
||||||
virtual void setScale(float scale) { Scale = scale; }
|
|
||||||
|
|
||||||
//! returns default color
|
//! returns default color
|
||||||
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
|
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
|
||||||
|
|
||||||
@ -298,7 +292,6 @@ namespace gui
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
float Scale = 1.0f;
|
|
||||||
video::SColor Colors[EGDC_COUNT];
|
video::SColor Colors[EGDC_COUNT];
|
||||||
s32 Sizes[EGDS_COUNT];
|
s32 Sizes[EGDS_COUNT];
|
||||||
u32 Icons[EGDI_COUNT];
|
u32 Icons[EGDI_COUNT];
|
||||||
|
101
src/log_types.cpp
Normal file
101
src/log_types.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Freeminer.
|
||||||
|
|
||||||
|
Freeminer is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Freeminer is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log_types.h"
|
||||||
|
#include "convert_json.h"
|
||||||
|
#include "irr_v3d.h"
|
||||||
|
#include "network/address.h"
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v2s16 &p)
|
||||||
|
{
|
||||||
|
s << "(" << p.X << "," << p.Y << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v2s32 &p)
|
||||||
|
{
|
||||||
|
s << "(" << p.X << "," << p.Y << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v2f &p)
|
||||||
|
{
|
||||||
|
s << "(" << p.X << "," << p.Y << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v3pos_t &p)
|
||||||
|
{
|
||||||
|
s << "(" << p.X << "," << p.Y << "," << p.Z << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v3f &p)
|
||||||
|
{
|
||||||
|
s << "(" << p.X << "," << p.Y << "," << p.Z << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USE_OPOS64
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v3opos_t &p)
|
||||||
|
{
|
||||||
|
s << "(" << p.X << "," << p.Y << "," << p.Z << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const std::map<v3pos_t, unsigned int> &p)
|
||||||
|
{
|
||||||
|
for (auto &i : p)
|
||||||
|
s << i.first << "=" << i.second << " ";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const irr::video::SColor &c)
|
||||||
|
{
|
||||||
|
s << "c32(" << c.color << ": a=" << c.getAlpha() << ",r=" << c.getRed()
|
||||||
|
<< ",g=" << c.getGreen() << ",b=" << c.getBlue() << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const irr::video::SColorf &c)
|
||||||
|
{
|
||||||
|
s << "cf32("
|
||||||
|
<< "a=" << c.getAlpha() << ",r=" << c.getRed() << ",g=" << c.getGreen()
|
||||||
|
<< ",b=" << c.getBlue() << ")";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "util/string.h"
|
||||||
|
std::ostream &operator<<(std::ostream &s, const std::wstring &w)
|
||||||
|
{
|
||||||
|
s << wide_to_utf8(w);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const Json::Value &json)
|
||||||
|
{
|
||||||
|
s << fastWriteJson(json);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const Address &addr)
|
||||||
|
{
|
||||||
|
addr.print(s);
|
||||||
|
// s << addr.getPort();
|
||||||
|
return s;
|
||||||
|
}
|
55
src/log_types.h
Normal file
55
src/log_types.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Freeminer.
|
||||||
|
|
||||||
|
Freeminer is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Freeminer is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOG_TYPES_HEADER
|
||||||
|
#define LOG_TYPES_HEADER
|
||||||
|
|
||||||
|
//#include "log.h" //for replacing log.h to log_types.h in includes
|
||||||
|
|
||||||
|
#include "irr_v2d.h"
|
||||||
|
#include "irr_v3d.h"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v2s16 &p);
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v2s32 &p);
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v2f &p);
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v3pos_t &p);
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v3f &p);
|
||||||
|
#if USE_OPOS64
|
||||||
|
std::ostream &operator<<(std::ostream &s, const v3opos_t &p);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <SColor.h>
|
||||||
|
std::ostream &operator<<(std::ostream &s, const irr::video::SColor &c);
|
||||||
|
std::ostream &operator<<(std::ostream &s, const irr::video::SColorf &c);
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
std::ostream &operator<<(std::ostream &s, const std::map<v3pos_t, unsigned int> &p);
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &s, const std::wstring &w);
|
||||||
|
|
||||||
|
namespace Json
|
||||||
|
{
|
||||||
|
class Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
//std::ostream &operator<<(std::ostream &s, const Json::Value &json);
|
||||||
|
|
||||||
|
class Address;
|
||||||
|
std::ostream &operator<<(std::ostream &s, const Address &addr);
|
||||||
|
|
||||||
|
#endif
|
@ -31,7 +31,7 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "threading/thread.h"
|
#include "threading/thread_vector.h"
|
||||||
#include "threading/concurrent_map.h"
|
#include "threading/concurrent_map.h"
|
||||||
#include "network/address.h"
|
#include "network/address.h"
|
||||||
|
|
||||||
@ -71,13 +71,13 @@ typedef int socket_t;
|
|||||||
const static unsigned short int adv_port = 29998;
|
const static unsigned short int adv_port = 29998;
|
||||||
static std::string ask_str;
|
static std::string ask_str;
|
||||||
|
|
||||||
lan_adv::lan_adv() : Thread("lan_adv")
|
lan_adv::lan_adv() : thread_vector("lan_adv")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void lan_adv::ask()
|
void lan_adv::ask()
|
||||||
{
|
{
|
||||||
if (!isRunning()) start();
|
reanimate();
|
||||||
|
|
||||||
if (ask_str.empty()) {
|
if (ask_str.empty()) {
|
||||||
Json::Value j;
|
Json::Value j;
|
||||||
@ -169,15 +169,14 @@ void lan_adv::send_string(const std::string &str)
|
|||||||
void lan_adv::serve(unsigned short port)
|
void lan_adv::serve(unsigned short port)
|
||||||
{
|
{
|
||||||
server_port = port;
|
server_port = port;
|
||||||
if (isRunning()) stop();
|
restart();
|
||||||
start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *lan_adv::run()
|
void *lan_adv::run()
|
||||||
{
|
{
|
||||||
BEGIN_DEBUG_EXCEPTION_HANDLER;
|
BEGIN_DEBUG_EXCEPTION_HANDLER;
|
||||||
|
|
||||||
setName("LanAdv" + (server_port ? std::string("Server") : std::string("Client")));
|
reg("LanAdv" + (server_port ? std::string("Server") : std::string("Client")));
|
||||||
|
|
||||||
UDPSocket socket_recv(true);
|
UDPSocket socket_recv(true);
|
||||||
int set_option_off = 0, set_option_on = 1;
|
int set_option_off = 0, set_option_on = 1;
|
||||||
|
@ -19,14 +19,14 @@ along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "json/json.h"
|
#include <json/value.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include "threading/thread.h"
|
#include "threading/thread_vector.h"
|
||||||
#include "threading/concurrent_map.h"
|
#include "threading/concurrent_map.h"
|
||||||
|
|
||||||
|
|
||||||
class lan_adv : public Thread
|
class lan_adv : public thread_vector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void *run();
|
void *run();
|
||||||
|
@ -50,6 +50,18 @@ void lan_get() {
|
|||||||
lan_adv_client.ask();
|
lan_adv_client.ask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (ask_str.empty()) {
|
||||||
|
Json::Value j;
|
||||||
|
j["cmd"] = "ask";
|
||||||
|
j["proto_min"] = Server::getProtocolVersionMin();
|
||||||
|
j["proto_max"] = Server::getProtocolVersionMax();
|
||||||
|
ask_str = fastWriteJson(j);
|
||||||
|
|
||||||
|
};
|
||||||
|
lan_adv_client.send_string(ask_str);
|
||||||
|
*/
|
||||||
|
|
||||||
bool lan_fresh() {
|
bool lan_fresh() {
|
||||||
auto result = lan_adv_client.fresh.load();
|
auto result = lan_adv_client.fresh.load();
|
||||||
lan_adv_client.fresh = false;
|
lan_adv_client.fresh = false;
|
||||||
|
@ -3,5 +3,6 @@ set(JTHREAD_SRCS
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/lock.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/lock.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/thread_vector.cpp
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
|
||||||
|
118
src/threading/thread_vector.cpp
Normal file
118
src/threading/thread_vector.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include "thread_vector.h"
|
||||||
|
#include "fm_porting.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "porting.h"
|
||||||
|
|
||||||
|
thread_vector::thread_vector(const std::string &name, int priority) :
|
||||||
|
m_name(name), m_priority(priority)
|
||||||
|
{
|
||||||
|
request_stop = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
thread_vector::~thread_vector()
|
||||||
|
{
|
||||||
|
join();
|
||||||
|
};
|
||||||
|
|
||||||
|
void thread_vector::func()
|
||||||
|
{
|
||||||
|
reg();
|
||||||
|
run();
|
||||||
|
};
|
||||||
|
|
||||||
|
void thread_vector::reg(const std::string &name, int priority)
|
||||||
|
{
|
||||||
|
if (!name.empty())
|
||||||
|
m_name = name;
|
||||||
|
|
||||||
|
porting::setThreadName(m_name.c_str());
|
||||||
|
g_logger.registerThread(m_name);
|
||||||
|
|
||||||
|
if (priority)
|
||||||
|
m_priority = priority;
|
||||||
|
if (m_priority)
|
||||||
|
porting::setThreadPriority(m_priority);
|
||||||
|
};
|
||||||
|
|
||||||
|
void thread_vector::start(const size_t n)
|
||||||
|
{
|
||||||
|
#if !NDEBUG
|
||||||
|
infostream << "start thread " << m_name << " n=" << n << std::endl;
|
||||||
|
#endif
|
||||||
|
request_stop = false;
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
workers.emplace_back(&thread_vector::func, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_vector::stop()
|
||||||
|
{
|
||||||
|
request_stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_vector::join()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
for (auto &worker : workers) {
|
||||||
|
try {
|
||||||
|
if (worker.joinable()) {
|
||||||
|
worker.join();
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
workers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_vector::restart(size_t n)
|
||||||
|
{
|
||||||
|
join();
|
||||||
|
start(n);
|
||||||
|
}
|
||||||
|
void thread_vector::reanimate(size_t n)
|
||||||
|
{
|
||||||
|
if (workers.empty()) {
|
||||||
|
start(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_vector::sleep(const int seconds)
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= seconds; ++i) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
if (request_stop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// JThread compat:
|
||||||
|
bool thread_vector::stopRequested()
|
||||||
|
{
|
||||||
|
return request_stop;
|
||||||
|
}
|
||||||
|
bool thread_vector::isRunning()
|
||||||
|
{
|
||||||
|
return !workers.empty();
|
||||||
|
}
|
||||||
|
void thread_vector::wait()
|
||||||
|
{
|
||||||
|
join();
|
||||||
|
};
|
||||||
|
void thread_vector::kill()
|
||||||
|
{
|
||||||
|
join();
|
||||||
|
};
|
||||||
|
void *thread_vector::run()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool thread_vector::isCurrentThread()
|
||||||
|
{
|
||||||
|
auto thread_me = std::hash<std::thread::id>()(std::this_thread::get_id());
|
||||||
|
for (auto &worker : workers)
|
||||||
|
if (thread_me == std::hash<std::thread::id>()(worker.get_id()))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
37
src/threading/thread_vector.h
Normal file
37
src/threading/thread_vector.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class thread_vector {
|
||||||
|
public:
|
||||||
|
std::vector<std::thread> workers;
|
||||||
|
std::atomic_bool request_stop;
|
||||||
|
|
||||||
|
thread_vector(const std::string &name = "Unnamed", int priority = 0);
|
||||||
|
virtual ~thread_vector();
|
||||||
|
|
||||||
|
virtual void func();
|
||||||
|
|
||||||
|
void reg (const std::string &name = "", int priority = 0);
|
||||||
|
void start (const size_t n = 1);
|
||||||
|
void restart (const size_t n = 1);
|
||||||
|
void reanimate (const size_t n = 1);
|
||||||
|
void stop ();
|
||||||
|
void join ();
|
||||||
|
|
||||||
|
void sleep(const int second);
|
||||||
|
// Thread compat:
|
||||||
|
|
||||||
|
bool stopRequested();
|
||||||
|
bool isRunning();
|
||||||
|
void wait();
|
||||||
|
void kill();
|
||||||
|
virtual void * run() = 0;
|
||||||
|
bool isCurrentThread();
|
||||||
|
protected:
|
||||||
|
std::string m_name;
|
||||||
|
int m_priority = 0;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user