source: trunk/src/gui/gui_environment.cc @ 541

Last change on this file since 541 was 520, checked in by epyon, 9 years ago
  • ecs updates
  • animation updates
  • ragdoll manager
  • lua has own random engine
  • several minor fixes
  • particle engine/particle group
  • shitload of other stuff
  • bullet world
File size: 8.0 KB
Line 
1// Copyright (C) 2012-2015 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/gui/gui_environment.hh"
8
9#include "nv/gui/gui_renderer.hh"
10
11        /*
12
13        TODO: parse a lua stylesheet as per Trac wiki
14
15        IDEA: Store everything in unordered_maps, with lua_value's?
16
17        A lua_value is a variant stores strings as const char* that deletes them on destructor?
18        Question is that there might not be much gained on speed anyway, due to Lua's speed.
19        Special function field allows delayed per parse execution?
20
21        */
22
23
24nv::gui::environment::environment( renderer* r )
25        : m_renderer( r )
26{
27        r->set_environment( this );
28        m_screen   = create_element( handle(), m_renderer->get_area() );
29}
30
31void nv::gui::environment::load_style( const string_view& filename )
32{
33        m_renderer->load_style( filename );
34}
35
36nv::gui::handle nv::gui::environment::create_element( const rectangle& r )
37{
38        return create_element( m_screen, r );
39}
40
41nv::gui::handle nv::gui::environment::create_element( handle parent, const rectangle& r )
42{
43        if ( parent.is_nil() ) parent = m_screen;
44
45        handle result  = m_elements.create();
46        element* e     = m_elements.get( result );
47        rectangle ar   = r;
48        rectangle full = m_renderer->get_area();
49
50        if ( ar.ul.x < 0 ) { ar.ul.x += full.lr.x; ar.lr.x += full.lr.x; }
51        if ( ar.ul.y < 0 ) { ar.ul.y += full.lr.y; ar.lr.y += full.lr.y; }
52
53        e->m_child_count = 0;
54        e->m_flags[ENABLED] = true;
55        e->m_flags[VISIBLE] = true;
56        e->m_flags[DIRTY]   = true;
57        e->m_render_data    = nullptr;
58        e->m_absolute = ar;
59        e->m_relative = ar;
60
61        if ( !parent.is_nil() ) // screen creation
62                add_child( parent, result );
63
64        return result;
65}
66
67void nv::gui::environment::destroy_element( handle e )
68{
69        element* dead_element = m_elements.get( e );
70        if ( dead_element == nullptr ) return;
71        destroy_children( e );
72        remove_child( dead_element->m_parent, e );
73
74        delete dead_element->m_render_data;
75        dead_element->m_render_data = nullptr;
76        dead_element->m_parent = handle();
77
78        m_elements.destroy( e );
79}
80
81void nv::gui::environment::update( handle e, uint32 elapsed )
82{
83        element* el = m_elements.get( e );
84        if ( !el ) return;
85        //      el->on_update( elapsed );
86        if ( el->m_flags[ENABLED] )
87        {
88                bool hover     = el->m_flags[HOVER];
89                bool new_hover = el->m_absolute.contains( m_mouse_position );
90                if ( hover != new_hover )
91                {
92                        el->m_flags[HOVER] = new_hover;
93                        // gain lose hover event
94                        m_renderer->on_hover_change( el );
95                }
96        }
97
98        if ( el->m_flags[VISIBLE] )
99        {
100                for ( handle i : el->m_children )
101                {
102                        update( i, elapsed );
103                }
104        }
105        if ( el->m_flags[DIRTY] || el->m_render_data == nullptr )
106        {
107                m_renderer->redraw( el, elapsed );
108                el->m_flags[DIRTY] = false;
109        }
110}
111
112void nv::gui::environment::draw( handle e )
113{
114        element* el = m_elements.get( e );
115        if ( !el ) return;
116        if ( el->m_flags[VISIBLE] )
117        {
118//              el->on_draw();
119                m_renderer->draw( el );
120                for ( handle i : el->m_children )
121                {
122                        draw(i);
123                }
124        }
125}
126
127void nv::gui::environment::update()
128{
129        update( m_screen, 0 );
130}
131
132void nv::gui::environment::draw()
133{
134        draw( m_screen );
135        m_renderer->draw();
136}
137
138void nv::gui::environment::add_child( handle child )
139{
140        add_child( m_screen, child );
141}
142
143void nv::gui::environment::add_child( handle parent, handle child )
144{
145        element* e = m_elements.get( child );
146        element* p = m_elements.get( parent );
147        if ( e && p )
148        {
149                remove_child( e->m_parent, child );
150                e->m_parent = parent;
151                p->m_children.push_back( child );
152                p->m_child_count++;
153        }
154}
155
156void nv::gui::environment::destroy_children( handle e )
157{
158        element* parent = m_elements.get(e);
159        if ( parent )
160        {
161                while ( !parent->m_children.empty() )
162                {
163                        destroy_element( parent->m_children.back() );
164                }
165        }
166}
167
168
169nv::gui::environment::~environment()
170{
171        destroy_children( handle() );
172        delete m_renderer;
173}
174
175bool nv::gui::environment::process_io_event( const io_event& ev )
176{
177        switch ( ev.type )
178        {
179//      case EV_KEY          :
180        case EV_MOUSE_BUTTON :
181                if ( ev.mbutton.pressed && ev.mbutton.button == MOUSE_LEFT )
182                {
183                        handle h = get_element( position( ev.mbutton.x, ev.mbutton.y ) );
184                        element* e = m_elements.get( h );
185                        if (e)
186                        if ( e->m_on_click ) e->m_on_click();
187
188                        set_selected( h );
189                        return true;
190                }
191                return false;
192        case EV_MOUSE_MOVE:
193                m_mouse_position = position( ev.mmove.x, ev.mmove.y );
194                return false;
195//      case EV_MOUSE_WHEEL  :
196        default:
197                break;
198        }
199        return false;
200}
201
202nv::string_view nv::gui::environment::get_string( shash64 h )
203{
204        return m_strings[h];
205}
206
207bool nv::gui::environment::set_selected( handle e )
208{
209        if ( e != m_selected )
210        {
211                element* eold = m_elements.get( m_selected );
212                element* el   = m_elements.get( e );
213                if ( eold )
214                {
215                        eold->m_flags[SELECTED] = false;
216                        m_renderer->on_select_change( eold );
217                }
218                if ( el )
219                {
220                        el->m_flags[SELECTED] = true;
221                        m_renderer->on_select_change( el );
222                }
223                m_selected = e;
224                return true;
225        }
226        return false;
227}
228
229bool nv::gui::environment::process_io_event( handle e, const io_event& ev )
230{
231        element* el = m_elements.get( e );
232        return el && el->m_parent.is_valid() ? process_io_event( el->m_parent, ev ) : false;
233}
234
235nv::gui::handle nv::gui::environment::get_element( const position& p )
236{
237        return get_deepest_child( m_screen, p );
238}
239
240nv::gui::handle nv::gui::environment::get_deepest_child( handle e, const position& p )
241{
242        element* el = m_elements.get(e);
243        if ( !el && !el->m_flags[VISIBLE] ) return handle();
244
245        handle result;
246        auto it = el->m_children.rbegin();
247
248        while ( it != el->m_children.rend() )
249        {
250                result = get_deepest_child( *it, p );
251                if ( result.is_valid() ) return result;
252                ++it;
253        }
254
255        if ( el->m_absolute.contains(p) ) return e;
256        return handle();
257}
258
259void nv::gui::environment::move_to_top( handle child )
260{
261        element* e      = m_elements.get( child );
262        element* parent = m_elements.get( e->m_parent );
263        if ( e && parent )
264        {
265                auto it = find( parent->m_children.begin(), parent->m_children.end(), child );
266                if ( it != parent->m_children.end() )
267                {
268                        parent->m_children.erase( it );
269                        parent->m_children.push_back( child );
270                        parent->m_flags[DIRTY] = true;
271                }       
272        }
273}
274
275void nv::gui::environment::set_relative( handle e, const rectangle& r )
276{
277        element* el = m_elements.get(e);
278        if ( el )
279        {
280                el->m_flags[DIRTY] = true;
281                el->m_relative     = r;
282                recalculate_absolute( e );
283        }
284}
285
286void nv::gui::environment::set_relative( handle e, const position& p )
287{
288        element* el = m_elements.get(e);
289        if ( el )
290        {
291                set_relative( e, rectangle( p, p + el->m_relative.get_size() ) );
292        }
293}
294
295void nv::gui::environment::recalculate_absolute( handle e )
296{
297        element* el = m_elements.get(e);
298        rectangle pabsolute = m_elements.get( el->m_parent )->m_absolute;
299        el->m_absolute = el->m_relative + pabsolute.ul;
300
301        for ( handle o : el->m_children )
302        {
303                recalculate_absolute( o );
304        }
305}
306
307void nv::gui::environment::set_class( handle e, const string_view& text )
308{
309        element* ep = m_elements.get(e);
310        if ( ep != nullptr )
311        {
312                ep->m_class        = m_strings.insert( text );
313                ep->m_flags[DIRTY] = true;
314                m_renderer->on_style_change( ep );
315        }
316}
317
318void nv::gui::environment::set_on_click( handle e, const function< void() >& on_click )
319{
320        element* ep = m_elements.get( e );
321        if ( ep != nullptr )
322        {
323                ep->m_on_click = on_click;
324        }
325}
326
327void nv::gui::environment::set_text( handle e, const string_twine& text )
328{
329        element* ep = m_elements.get(e);
330        if ( ep != nullptr )
331        {
332                // TODO : implement twine == operator
333                ep->m_text.assign( text );
334                ep->m_flags[DIRTY] = true;
335        }
336}
337
338void nv::gui::environment::remove_child( handle parent, handle child )
339{
340        element* p = m_elements.get( parent );
341        if ( p )
342        {
343                auto it = find( p->m_children.begin(), p->m_children.end(), child );
344                if ( it != p->m_children.end() )
345                {
346                        element* e = m_elements.get( *it );
347                        e->m_parent = handle();
348                        p->m_children.erase( it );
349                }
350        }
351}
352
Note: See TracBrowser for help on using the repository browser.