Jump to content

klepto2

Developers
  • Posts

    859
  • Joined

  • Last visited

Posts posted by klepto2

  1. Don't know if this is needed for other os than windows but if you create a child window it might be useful to not show it in the taskbar like for tooltips or like UAK does it with the combobox. A hack to achieve this is doing the following:

    _window = CreateWindow("", 0, 0, 0, 0, displays[0], WindowStyles::WINDOW_HIDDEN | WindowStyles::WINDOW_CHILD);
    SetWindowLongA(_window->GetHandle(), GWL_EXSTYLE, (GetWindowLong(_window->GetHandle(), GWL_EXSTYLE) | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW);
       

     

  2. static const and scoped enums are 2 different things. the current enums look like a mix of enums names for constants. Normally only constants are uppercase. The thing is you don't need the uppercase-separated-by-underscore approach. You can keep the uppercase names of course:

    CreateTextfield(0,0,250,20,ui->root, TextfieldStyle::DEFAULT); // you can now clearly say what enum is used.

    with your approach you can't have something like this:

    enum VerticalAlignment
    {
      TOP,BOTTOM,CENTER
    };
    
    enum HorizontalAlignment
    {
      LEFT,RIGHT,CENTER
    };

    which leads to the need of the underscore approach.

    with scoped enums this is legal:

    enum class VerticalAlignment
    {
      TOP,BOTTOM,CENTER
    };
    
    enum class HorizontalAlignment
    {
      LEFT,RIGHT,CENTER
    };

    as mentioned in the above post in my opinion it feels cleaner and is more collision safe with other libraries.

    • Like 1
  3. Currently the enums in UAK are defined as unscoped enums like this:

    enum TextFieldStyle
    	{
    		TEXTFIELD_READONLY = 1,
    		//TEXTFIELD_PASSWORD = 2,
    		TEXTFIELD_TEXTCHANGEACTIONEVENT = 4,
    		TEXTFIELD_LOSEFOCUSACTIONEVENT = 8,
    		TEXTFIELD_ENTERKEYACTIONEVENT = 16,
    		TEXTFIELD_DEFAULT = TEXTFIELD_LOSEFOCUSACTIONEVENT + TEXTFIELD_ENTERKEYACTIONEVENT,
    		//TEXTFIELD_NUMBER = 8,
    		//TEXTFIELD_INTEGER = 16,
    		//TEXTFIELD_FILEPATH = 32,
    		TEXTFIELD_PASSWORD = 64
    	};

    I suggest to follow the common c++ suggestions to use scoped enums instead:

    enum class TextFieldStyle
    {
    		ReadOnly = 1,
    		Password = 2,
    		TextChangeActionEvent = 4,
    		LoseFocusActionEvent = 8,
    		EnterKeyActionEvent = 16,
    		Default = LoseFocusActionEvent + EnterKeyActionEvent,
    };

    The scoped enums have much more possibilities:

    1. You can have the same enum-value name across multiple enums (eg Default or Left) 

    2. enums can have a different value type instead of just int

    3. the code completion is much more intuitive in most IDEs.

    4. the code is more readable (in my opinion)

  4. class TooltipInfo : public Object
    {
    public:
        shared_ptr<Widget> target;
        shared_ptr<Widget> tooltipWidget;
    };
    
    enum class TooltipState
    {
        Pending,
        Show,
        Showing,
        Hiding,
        Hide,
    };
    
    class TooltipService
    {
        static vector<shared_ptr<TooltipInfo>> _tooltipInfos;
        static bool _initialized;
        static TooltipState _state;
        static shared_ptr<Window> _window;
        static shared_ptr<Interface> _ui;
        static bool Enter(const Event&, shared_ptr<Object>);
        static bool Leave(const Event&, shared_ptr<Object>);
        static bool Tick(const Event&, shared_ptr<Object>);
        static void Init();
        static shared_ptr<Timer> _timer;
        static shared_ptr<TooltipInfo> _activeWidget;
        static int _timerstart;
        static void ShowTooltip(shared_ptr<TooltipInfo> widget);
        static void HideTooltip();
    public:
        static void RegisterTooltip(shared_ptr<Widget> target, shared_ptr<Widget> tooltipControl = nullptr);
    };
    
    vector<shared_ptr<TooltipInfo>> TooltipService::_tooltipInfos = vector<shared_ptr<TooltipInfo>>();
    bool TooltipService::_initialized = false;
    shared_ptr<TooltipInfo> TooltipService::_activeWidget = nullptr;
    shared_ptr<Timer> TooltipService::_timer = nullptr;
    int TooltipService::_timerstart = -1;
    TooltipState TooltipService::_state = TooltipState::Pending;
    shared_ptr<Window> TooltipService::_window = nullptr;
    shared_ptr<Interface> TooltipService::_ui = nullptr;
    
    bool TooltipService::Tick(const Event& ev, shared_ptr<Object> obj)
    {
        if (_state == TooltipState::Show && (Millisecs() - _timerstart) > 500)
        {
            ShowTooltip(_activeWidget);
        }
        else if (_state == TooltipState::Hiding && (Millisecs() - _timerstart) > 200)
        {
            _state = TooltipState::Hide;
        }
        else if (_state == TooltipState::Hide)
        {
            HideTooltip();
        }
    
        return false;
    }
    
    void TooltipService::ShowTooltip(shared_ptr<TooltipInfo> widget)
    {
        if (_state == TooltipState::Show)
        {
            HideTooltip();
        }
    
        if (widget->tooltipWidget == nullptr)
        {
            return;
        }
    
        auto mainwindow = widget->target->gui->GetWindow();
        auto bordersize = mainwindow->GetBorder();
        auto mp = mainwindow->GetMousePosition();
        auto wp = mainwindow->GetPosition();
        _window->SetShape(mp.x + wp.x +15, mp.y + wp.y + 50, widget->tooltipWidget->size.x, widget->tooltipWidget->size.y);
        widget->tooltipWidget->Show();
        _window->Show();
        _state = TooltipState::Showing;
    }
    
    void TooltipService::HideTooltip()
    {
        _window->Hide();
        _state = TooltipState::Pending;
    }
    
    bool TooltipService::Enter(const Event& ev, shared_ptr<Object> obj)
    {
        _activeWidget = obj->As<TooltipInfo>();
        _timerstart = Millisecs();
        _state = TooltipState::Show;
        return false;
    }
    
    bool TooltipService::Leave(const Event& ev, shared_ptr<Object> obj)
    {
        _activeWidget = nullptr;
        _state = TooltipState::Hiding;
        _timerstart = Millisecs();
        return false;
    }
    
    void TooltipService::Init()
    {
        auto displays = GetDisplays();
        _window = CreateWindow("", 0, 0, 0, 0, displays[0], WindowStyles::WINDOW_HIDDEN | WindowStyles::WINDOW_CHILD);
        SetWindowLongA(_window->GetHandle(), GWL_EXSTYLE, (GetWindowLong(_window->GetHandle(), GWL_EXSTYLE) | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW);
        _ui = CreateInterface(_window);
        _timer = CreateTimer(50);
        ListenEvent(EventID::EVENT_TIMERTICK, _timer, TooltipService::Tick);
        _initialized = true;
    }
    
    void TooltipService::RegisterTooltip(shared_ptr<Widget> target, shared_ptr<Widget> tooltipControl)
    {
        if (!_initialized)
        {
            Init();
        }
    
        auto info = make_shared<TooltipInfo>();
        info->target = target;
        info->tooltipWidget = tooltipControl;
    
        if (tooltipControl != nullptr)
        {
            tooltipControl->Hide();
            tooltipControl->SetParent(_ui->root);
        }
    
        _tooltipInfos.push_back(info);
    
        ListenEvent(EventID::EVENT_MOUSEENTER, target, TooltipService::Enter, info);
        ListenEvent(EventID::EVENT_MOUSELEAVE, target, TooltipService::Leave, info);
    }

     

    Very simple tooltip system (just a small prototype) (win32 only, for other remove the SetWindowLongA part in the init method).

    This is how to use it:

        auto tooltipControl = CreatePanel(0, 0, 250, 80, ui->root, PANEL_BORDER);
        tooltipControl->SetColor(Vec4(0.7,0.7,0.7, 1.0), WidgetColor::WIDGETCOLOR_BACKGROUND);
    
        auto tooltipLabel = CreateLabel("Some tooltip.", 0, 0, tooltipControl->size.x, tooltipControl->size.y, tooltipControl, LabelStyle::LABEL_CENTER | LabelStyle::LABEL_MIDDLE);
        tooltipLabel->SetLayout(1, 1, 1, 1);
    
        TooltipService::RegisterTooltip(toolbarbutton_open, tooltipControl);
        TooltipService::RegisterTooltip(toolbarbutton_save);
        TooltipService::RegisterTooltip(toolbarbutton_options);
        TooltipService::RegisterTooltip(toolbarbutton_help);

     

    • Haha 1
  5. Hi!

    I was on vacation the last 2 weeks so i couldn't reply earlier. Take a look here: 

    I am currently working on a full featured layout system with Container Gadgets which will work like (kind of) the way you can layout things in xaml or in other GUI libraries. I will post more info on that new system in a later blog entry but in general it should work the way you described. There will be Container, Grid, Flow, Stackpanel and other widgets to control the layout as well as additional layouting features (Alignment, Margin, Padding, etc.)

     

    • Like 1
  6. Well, while I agree that too high values might lead to problems I doubt that this is the case here. 

    1. it only occurs while using the knob dragging with the mouse, setting the value with the mousewheel or directly doesn't have the issue
    2. When I set the values to 2 and 8 I lose a precision of 100px in the case i want Pixel Perfect scrolling ( Imageviewer)

     

     

  7. It seems there is a bug where you can't scroll the slider using mousedragging when the containing window is too small:

    #include "UltraEngine.h"
    
    using namespace UltraEngine;
    
    bool RescaleUI(const Event& event, shared_ptr<Object> extra)
    {
    	float dpiscale = float(event.data) / 100.0f;
    	auto ui = dynamic_pointer_cast<Interface>(extra);
    	ui->SetScale(dpiscale);
    	auto window = dynamic_pointer_cast<Window>(event.source);
    	window->SetShape(event.position.x, event.position.y, event.size.x, event.size.y);
    	return true;
    }
    
    int main(int argc, const char* argv[])
    {
    	//Get displays
    	auto displays = GetDisplays();
    	if (displays.empty()) return 1;
    	float dpiscale = displays[0]->scale;
    
    	//Create window
    	auto mainwindow = CreateWindow("Ultra App Kit", 0, 0, 300 * dpiscale, 400 * dpiscale, displays[0], WINDOW_HIDDEN | WINDOW_CENTER | WINDOW_TITLEBAR | WINDOW_RESIZABLE);
    
    	//Create user interface
    	auto ui = CreateInterface(mainwindow);
    	iVec2 sz = ui->root->ClientSize();
    	auto label = CreateSlider(0, 0, 20, sz.y, ui->root, SLIDER_SCROLLBAR | SLIDER_VERTICAL);
    	label->SetLayout(1, 0, 1, 1);
    	label->SetRange(200,800);
    
    	//Enable DPI scaling changes
    	ui->SetScale(dpiscale);
    	ListenEvent(EVENT_WINDOWDPICHANGED, mainwindow, RescaleUI, ui);
    	
    	//Show the window
    	mainwindow->Show();
    	mainwindow->Activate();
    
    	while (true)
    	{
    		const Event event = WaitEvent();
    		switch (event.id)
    		{
    		case EVENT_WIDGETSELECT:
    			break;
    		case EVENT_WIDGETACTION:
    			break;
    		case EVENT_WINDOWCLOSE:
    			if (event.source == mainwindow) return 0;
    			break;
    		}
    	}
    	return 0;
    }

    When you start this, you can't scroll the slider, but if you resize the window to some extend the dragging starts working.

  8. Hi, 

    i have used SWIG with Leadwerks succesfully in the past and also use it currently from time to time.

    You can create your own dll by using the Leadwerks.lib under windows or the Leadwerks.a under Linux. Just create a new Leadwerksproject, remove all sources and add the generated header from swig into the project. Then change the project properties to compile to a dll (or the same for linux).

    For getting a complete Wrapper you need to fix alot of definitions and make use of a lot of SWIG tricks. I would recommend to start only with the classes and things made public to lua and extend on that.

     

  9. Well, sure the Skybox might not be needed for Lights, but is needed for Probes. In general the Camera provides functions to render the scene and this is needed for probes and shadowmaps. 

    You get all the info with the API-reference.xml as well.  the filename usually looks like this: 

    API-Reference_Object_Entity_Camera_Light_DirectionalLight

    Strip the beginning and split by _, then you get the whole hierarchy of the class. In some cases there is a something like Object_Math_AABB where Math is not a real class, but if you register all class names before parsing the actual class you can identify these and ignore those 'pseudo' classes. 

     

  10. I really like this feature in Notepad++ and VS2013. According to scintilla's website it should be supported. Feature is called "highlight.current.word".

     

    http://www.scintilla.org/SciTEDoc.html

     

    this is not the Documentation of Scintilla, it is the documentation of Scite,a Texteditor which uses Scintilla and is developed by the same guys developing scintilla. The implemntation is unfortuntly no one liner as you assumed. Why it should be no big Task, such Features could bring a big Performance Impact if not done right.

  11. Hi,

     

    it looks like you're mixing a matrial shader and a postprocess shader. should this shader work per instance or as a post process shader?

     

    If it should be a postprocess shader:

     

    These variables:


    //Inputs
    in vec2 ex_texcoords0;
    in vec4 ex_color;
    in float ex_selectionstate;
    in vec3 ex_VertexCameraPosition;
    in vec3 ex_normal;
    in vec3 ex_tangent;
    in vec3 ex_binormal;
    in float clipdistance0;
    [/Code]

     

    are not available and Need to be calculated from the depth/normal buffer provided via a lua part of the post process effect.

  12. as Leadwerks does use a deffered renderer i could imagine one way:

     

    Render the voxel terrain into a texture buffer with multiple channels:

    normals, texture coords and position

     

    then do postprocessing on it and interpolate or blur each channel to smooth it out. Then apply the the blurred textures on a projected plane and manipulate the fragment values based on the smoothed channels.

  13. while its representation is a 3d mesh or better a bunch of smaller 3d meshes it is bound to heightmap which is limited to 0..1 or 0..255 values depending on the internal format. Also a terrain system is a very performance hungry system in every engine so the culling, position calculation etc needs to be very optimized and if you can rotate, move or scale a terrain you always need add some cpu consuming matrix math to nearly each calculation.

     

    I agree that moving a terrain should be possible without much performance loss (it more or less just an offset addition), but scaling and rotating are too calculation heavy for such a system and can break the whole performance.

×
×
  • Create New...