Added autorun setting. Fixed greying of options that are not supported by the engine. Fixed keyboard navigation for general widgets (special menus might still be annoying). git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5285 fc73d0e0-1445-4013-8a0c-d673dee63da5
675 lines
19 KiB
C++
675 lines
19 KiB
C++
/***************************************************************************
|
|
Basic frame, containing sub-items.
|
|
Logically the parent of menu objects. Also used for tabs.
|
|
*/
|
|
|
|
#ifndef MITEM_FRAME_QC__
|
|
#define MITEM_FRAME_QC__
|
|
|
|
class mitem_vslider : mitem
|
|
{
|
|
virtual float(vector pos, float scan, float char, float down) item_keypress;
|
|
virtual void(vector pos) item_draw;
|
|
void() mitem_vslider;
|
|
float val;
|
|
float minv;
|
|
float maxv;
|
|
float stride; //size of one 'notch'
|
|
};
|
|
|
|
class mitem_frame : mitem
|
|
{
|
|
virtual void(mitem newfocus, float changedflag) item_focuschange;
|
|
virtual float(vector pos, float scan, float char, float down) item_keypress;
|
|
virtual void() item_resized;
|
|
virtual void(vector pos) item_draw;
|
|
virtual void() item_remove;
|
|
virtual void(mitem fromitem, string cmd) item_execcommand;
|
|
|
|
mitem item_children;
|
|
mitem item_mactivechild;
|
|
mitem item_kactivechild;
|
|
mitem item_exclusive;
|
|
|
|
mitem_vslider vslider; //displayed if any client item's max[y] > our item_size[y]
|
|
vector item_framesize; //x=sides, y=top, z=bottom
|
|
float frame_hasscroll;
|
|
|
|
static mitem(string title) findchildtext;
|
|
static mitem(string title) findchildcmd;
|
|
static void(mitem newitem, float originflags, vector originmin, vector originmax) add;
|
|
static void(mitem newitem, vector pos) adda;
|
|
static void(mitem newitem, vector originmin, vector originmax) addm;
|
|
static void(mitem newitem, float originflags, vector originmin, vector originmax) addr;
|
|
static void(mitem newitem, float ypos) addc;
|
|
|
|
void() mitem_frame =
|
|
{
|
|
item_flags |= IF_ISFRAME;
|
|
};
|
|
};
|
|
|
|
void(mitem fromitem, string cmd) mitem_frame::item_execcommand =
|
|
{
|
|
if (item_parent)
|
|
item_parent.item_execcommand(fromitem, cmd);
|
|
else
|
|
localcmd(strcat(cmd, "\n"));
|
|
};
|
|
|
|
mitem(string title) mitem_frame::findchildtext =
|
|
{
|
|
mitem ch;
|
|
for (ch = item_children; ch; ch = ch.item_next)
|
|
{
|
|
if (ch.item_text == title)
|
|
return ch;
|
|
}
|
|
return __NULL__;
|
|
};
|
|
mitem(string title) mitem_frame::findchildcmd =
|
|
{
|
|
mitem ch;
|
|
for (ch = item_children; ch; ch = ch.item_next)
|
|
{
|
|
if (ch.item_command == title)
|
|
return ch;
|
|
}
|
|
return __NULL__;
|
|
};
|
|
|
|
|
|
//adds an item with the desired origin settings
|
|
void(mitem newitem, float originflags, vector originmin, vector originmax) mitem_frame::add =
|
|
{
|
|
newitem.item_next = item_children;
|
|
item_children = newitem;
|
|
newitem.item_parent = this;
|
|
|
|
//set up position and resize
|
|
newitem.resizeflags = originflags;
|
|
newitem.mins = originmin;
|
|
newitem.maxs = originmax;
|
|
mitem_parentresized(newitem, [item_size[0] - item_framesize[0]*2, item_size[1] - (item_framesize[1] + item_framesize[2])]);
|
|
newitem.item_resized();
|
|
|
|
item_flags |= IF_CLIENTMOVED; //make sure it happens.
|
|
|
|
// if (!item_kactivechild && (newitem.item_flags & IF_SELECTABLE))
|
|
// item_focuschange(newitem, IF_KFOCUSED);
|
|
};
|
|
|
|
//adds an item to the parent with an absolute position relative to the parent's top-left. objects are expected to already have a size specified.
|
|
void(mitem newitem, vector pos) mitem_frame::adda =
|
|
{
|
|
local vector parentsize = [item_size[0] - item_framesize[0]*2, item_size[1] - (item_framesize[1] + item_framesize[2])];
|
|
newitem.item_next = item_children;
|
|
item_children = newitem;
|
|
newitem.item_parent = this;
|
|
|
|
newitem.resizeflags = RS_X_MIN_PARENT_MIN | RS_X_MAX_OWN_MIN | RS_Y_MIN_PARENT_MIN | RS_Y_MAX_OWN_MIN;
|
|
newitem.mins = pos;
|
|
newitem.maxs = newitem.item_size;
|
|
|
|
mitem_parentresized(newitem, parentsize);
|
|
newitem.item_resized();
|
|
|
|
item_flags |= IF_CLIENTMOVED; //make sure it happens.
|
|
|
|
// if (!item_kactivechild && (newitem.item_flags & IF_SELECTABLE))
|
|
// item_focuschange(newitem, IF_KFOCUSED);
|
|
};
|
|
|
|
//adds an item to the parent in reverse order (ie: at the tail, so the actual order in code)
|
|
void(mitem newitem, float originflags, vector originmin, vector originmax) mitem_frame::addr =
|
|
{
|
|
local vector parentsize = [item_size[0] - item_framesize[0]*2, item_size[1] - (item_framesize[1] + item_framesize[2])];
|
|
if (item_children)
|
|
{
|
|
local mitem prev;
|
|
for (prev = item_children; prev.item_next; prev = prev.item_next)
|
|
;
|
|
prev.item_next = newitem;
|
|
newitem.item_next = __NULL__;
|
|
}
|
|
else
|
|
{
|
|
newitem.item_next = item_children;
|
|
item_children = newitem;
|
|
}
|
|
newitem.item_parent = this;
|
|
|
|
newitem.resizeflags = originflags;
|
|
newitem.mins = originmin;
|
|
newitem.maxs = originmax;
|
|
mitem_parentresized(newitem, parentsize);
|
|
newitem.item_resized();
|
|
|
|
item_flags |= IF_CLIENTMOVED; //make sure it happens.
|
|
|
|
// if (!item_kactivechild && (newitem.item_flags & IF_SELECTABLE))
|
|
// item_focuschange(newitem, IF_KFOCUSED);
|
|
};
|
|
|
|
//adds an item on the parent with the x coord centered, and absolute y.
|
|
//if multiple items are at the same ypos, it will recenter all with respect to the others
|
|
void(mitem newitem, float ypos) mitem_frame::addc =
|
|
{
|
|
float w, c;
|
|
local mitem prev;
|
|
local vector parentsize = [item_size[0] - item_framesize[0]*2, item_size[1] - (item_framesize[1] + item_framesize[2])];
|
|
|
|
newitem.item_next = item_children;
|
|
item_children = newitem;
|
|
newitem.item_position[1] = ypos;
|
|
newitem.item_position[0] = (parentsize[0] - newitem.item_size[0])*0.5;
|
|
newitem.item_parent = this;
|
|
|
|
|
|
newitem.resizeflags = RS_X_MIN_PARENT_MID | RS_X_MAX_OWN_MIN | RS_Y_MIN_PARENT_MIN | RS_Y_MAX_OWN_MIN;
|
|
newitem.mins[0] = 0;
|
|
newitem.mins[1] = ypos;
|
|
newitem.maxs = newitem.item_size;
|
|
|
|
//count the width of the other items at this height.
|
|
w = 0;
|
|
c = 0;
|
|
for (prev = item_children; prev; prev = prev.item_next)
|
|
if (prev.resizeflags == newitem.resizeflags && prev.mins[1] == ypos && prev.maxs[1] == newitem.maxs[1])
|
|
{
|
|
w += prev.maxs[0];
|
|
c += 1;
|
|
}
|
|
|
|
//distribute them evenly (from the right, because its add-at-head)
|
|
w += (c-1)*16; //this much gap space
|
|
for (prev = item_children; prev; prev = prev.item_next)
|
|
{
|
|
if (prev.resizeflags == newitem.resizeflags && prev.mins[1] == ypos && prev.maxs[1] == newitem.maxs[1])
|
|
{
|
|
w -= prev.maxs[0];
|
|
prev.mins[0] = (w+prev.maxs[0])/-2;
|
|
mitem_parentresized(prev, parentsize);
|
|
w -= 16;
|
|
}
|
|
}
|
|
newitem.item_resized();
|
|
|
|
item_flags |= IF_CLIENTMOVED; //make sure it happens.
|
|
|
|
// if (!item_kactivechild && (newitem.item_flags & IF_SELECTABLE))
|
|
// item_focuschange(newitem, IF_KFOCUSED);
|
|
};
|
|
|
|
//Adds the item in the exact middle of the parent, in both axis
|
|
void(mitem newitem, vector min, vector max) mitem_frame::addm =
|
|
{
|
|
this.add(newitem, RS_X_MIN_PARENT_MID|RS_Y_MIN_PARENT_MID | RS_X_MAX_PARENT_MID|RS_Y_MAX_PARENT_MID, min, max);
|
|
};
|
|
|
|
//updates this.item_activechild, and calls focus notifications to ensure things get the message.
|
|
//flag should be IF_MFOCUSED or IF_KFOCUSED
|
|
void(mitem newfocus, float flag) mitem_frame::item_focuschange =
|
|
{
|
|
local mitem it;
|
|
|
|
if (newfocus == this)
|
|
{
|
|
//our focus didn't change, but the parent is telling us that *it* got changed while we're the focus
|
|
if (flag & IF_MFOCUSED)
|
|
{
|
|
if (item_parent.item_flags & IF_MFOCUSED && item_parent.item_mactivechild == this)
|
|
item_flags |= IF_MFOCUSED;
|
|
else
|
|
item_flags = item_flags - (item_flags&IF_MFOCUSED);
|
|
//and tell the child
|
|
it = item_mactivechild;
|
|
if (it)
|
|
if (it.item_focuschange)
|
|
it.item_focuschange(it, IF_MFOCUSED);
|
|
}
|
|
if (flag & IF_KFOCUSED)
|
|
{
|
|
if (item_parent.item_flags & IF_KFOCUSED && item_parent.item_kactivechild == this)
|
|
item_flags |= IF_KFOCUSED;
|
|
else
|
|
item_flags = item_flags - (item_flags&IF_KFOCUSED);
|
|
//and tell the child
|
|
it = item_kactivechild;
|
|
if (it)
|
|
if (it.item_focuschange)
|
|
it.item_focuschange(it, IF_KFOCUSED);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ((flag & IF_MFOCUSED) && item_mactivechild != newfocus)
|
|
{
|
|
//make key focus follow the mouse cursor. this should probably only apply to button menus or something? :s
|
|
if (newfocus && (item_flags & IF_FOCUSFOLLOWSMOUSE))
|
|
flag |= IF_KFOCUSED;
|
|
|
|
it = item_mactivechild;
|
|
item_mactivechild = newfocus;
|
|
if (it)
|
|
{
|
|
it.item_flags = it.item_flags - (it.item_flags&IF_MFOCUSED);
|
|
if (it.item_focuschange)
|
|
it.item_focuschange(it, IF_MFOCUSED);
|
|
}
|
|
it = item_mactivechild;
|
|
if (it)
|
|
{
|
|
it.item_flags = it.item_flags | (item_flags & IF_MFOCUSED);
|
|
if (it.item_focuschange)
|
|
it.item_focuschange(it, IF_MFOCUSED);
|
|
}
|
|
}
|
|
|
|
if ((flag & IF_KFOCUSED) && item_kactivechild != newfocus)
|
|
{
|
|
it = item_kactivechild;
|
|
item_kactivechild = newfocus;
|
|
if (it)
|
|
{
|
|
it.item_flags = it.item_flags - (it.item_flags&IF_KFOCUSED);
|
|
if (it.item_focuschange)
|
|
it.item_focuschange(it, IF_KFOCUSED);
|
|
}
|
|
it = item_kactivechild;
|
|
if (it)
|
|
{
|
|
it.item_flags = it.item_flags | (item_flags & IF_KFOCUSED);
|
|
if (it.item_focuschange)
|
|
it.item_focuschange(it, IF_KFOCUSED);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
float(vector pos, float scan, float char, float down) mitem_vslider::item_keypress =
|
|
{
|
|
if (down != 1)
|
|
{
|
|
if (scan == K_MOUSE1 && ui.mgrabs == this)
|
|
ui.mgrabs = __NULL__;
|
|
return FALSE;
|
|
}
|
|
if (scan == K_MWHEELDOWN)
|
|
val = bound(minv, val+stride, maxv);
|
|
else if (scan == K_MWHEELUP)
|
|
val = bound(minv, val-stride, maxv);
|
|
else if (scan == K_MOUSE1)
|
|
ui.mgrabs = this;
|
|
else
|
|
return FALSE;
|
|
return TRUE;
|
|
};
|
|
void(vector pos) mitem_vslider::item_draw =
|
|
{
|
|
float f;
|
|
float w = item_size[0];
|
|
float h = item_size[1];
|
|
float isize = w;
|
|
|
|
vector v = drawgetimagesize("scrollbars/slider.tga");
|
|
|
|
if (v != '0 0 0')
|
|
{
|
|
ui.drawpic(pos, "scrollbars/arrow_up.tga", [w, w], '1 1 1', item_alpha, 0); //top
|
|
pos_y += w;
|
|
h -= w*2;
|
|
ui.drawpic(pos + [0, h], "scrollbars/arrow_down.tga", [w, w], '1 1 1', item_alpha, 0); //bottom
|
|
ui.drawpic(pos, "scrollbars/slidebg.tga", [w, h], '1 1 1', item_alpha, 0); //back-middle
|
|
|
|
isize = (v_y * w) / (v_x);
|
|
if (isize > h/2)
|
|
isize = h/2;
|
|
}
|
|
else
|
|
{
|
|
// ui.drawfill(pos, [w, w], '1 1 1', item_alpha, 0); //top
|
|
// pos_y += w;
|
|
// h -= w*2;
|
|
// ui.drawfill(pos + [0, h], [w, w], '1 1 1', item_alpha, 0); //bottom
|
|
ui.drawfill(pos, [w, h], '0.5 0.5 0.5', item_alpha, 0); //back-middle
|
|
}
|
|
|
|
if (ui.mgrabs == this)
|
|
{
|
|
f = (ui.mousepos[1] - pos_y - (isize/2))/(h - isize);
|
|
f = bound(0, f, 1);
|
|
val = minv + (f * (maxv - minv));
|
|
}
|
|
else
|
|
f = bound(0, (val - minv) / (maxv - minv), 1);
|
|
|
|
h -= isize;
|
|
if (v != '0 0 0')
|
|
ui.drawpic(pos + [0, h*f], "scrollbars/slider.tga", [w, isize], '1 1 1', item_alpha, 0); //back-middle
|
|
else
|
|
ui.drawfill(pos + [0, h*f], [w, isize], '1 1 1', item_alpha, 0); //back-middle
|
|
};
|
|
void() mitem_vslider::mitem_vslider =
|
|
{
|
|
item_size[0] = 16;
|
|
item_size[1] = 128;
|
|
};
|
|
|
|
//does NOT wrap.
|
|
//does NOT pass go.
|
|
static mitem(mitem item, float upwards) menu_simplenextitem =
|
|
{
|
|
mitem_frame menu = item.item_parent;
|
|
mitem prev;
|
|
if (upwards)
|
|
{
|
|
if (item)
|
|
{
|
|
item = item.item_next;
|
|
if (!item)
|
|
return __NULL__;
|
|
return item;
|
|
}
|
|
else
|
|
return __NULL__;
|
|
}
|
|
else
|
|
{
|
|
for(prev = menu.item_children; prev.item_next; prev = prev.item_next)
|
|
{
|
|
if (prev.item_next == item)
|
|
return prev;
|
|
}
|
|
return __NULL__;
|
|
}
|
|
};
|
|
|
|
//finds the next/prev item through multiple children, returning NULL when it runs out of items in the sequence.
|
|
//call this with item==null to find the first item in the sequence (to handle wraps).
|
|
static mitem(mitem_frame menu, float upwards, mitem item) menu_findnextitem =
|
|
{
|
|
mitem_frame frame;
|
|
mitem citem;
|
|
|
|
if (item && (item.item_flags & IF_ISFRAME))
|
|
{
|
|
frame = (mitem_frame)item;
|
|
citem = menu_findnextitem(frame, upwards, frame.item_kactivechild?frame.item_kactivechild:frame.item_mactivechild);
|
|
if (citem)
|
|
return citem;
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
if (!item)
|
|
{ //we go for the opposite end here, as we assume to be starting/unfocused
|
|
item = menu.item_children;
|
|
if (!upwards && item)
|
|
{
|
|
while(item.item_next)
|
|
item = item.item_next;
|
|
}
|
|
}
|
|
else
|
|
item = menu_simplenextitem(item, upwards);
|
|
|
|
if (!item)
|
|
{ //we reached the end of the list, let the parent frame try its next
|
|
return __NULL__;
|
|
}
|
|
|
|
if (item.item_flags & IF_ISFRAME)
|
|
{ //if the next item is a frame, try and select its first element instead
|
|
frame = (mitem_frame)item;
|
|
citem = menu_findnextitem(frame, upwards, __NULL__);
|
|
if (citem)
|
|
return citem;
|
|
}
|
|
|
|
if (item.item_flags & IF_INVISIBLE)
|
|
continue;
|
|
if (item.item_flags & IF_SELECTABLE)
|
|
return item;
|
|
}
|
|
|
|
};
|
|
static void(mitem item) menu_deselectitem =
|
|
{
|
|
if (!item)
|
|
return;
|
|
if (item && (item.item_flags & IF_ISFRAME))
|
|
{
|
|
mitem_frame frame = (mitem_frame)item;
|
|
if (frame.item_kactivechild)
|
|
menu_deselectitem(frame.item_kactivechild);
|
|
}
|
|
item.item_focuschange(__NULL__, IF_KFOCUSED); //deselect the previous one
|
|
};
|
|
static void(mitem item) menu_selectitem =
|
|
{
|
|
if (!item)
|
|
return;
|
|
mitem_frame menu = item.item_parent;
|
|
if (menu)
|
|
{
|
|
if (menu.item_kactivechild != item)
|
|
menu_deselectitem(menu.item_kactivechild);
|
|
menu_selectitem(menu);
|
|
menu.item_focuschange(item, IF_KFOCUSED); //focus on the new
|
|
}
|
|
};
|
|
void(mitem_frame rootmenu, float upwards) menu_selectnextitem =
|
|
{
|
|
mitem item = menu_findnextitem(rootmenu, upwards, rootmenu.item_kactivechild?rootmenu.item_kactivechild:rootmenu.item_mactivechild);
|
|
if (!item)
|
|
item = menu_findnextitem(rootmenu, upwards, __NULL__);
|
|
|
|
menu_selectitem(item);
|
|
item.item_focuschange(item, IF_KFOCUSED); //focus on the new
|
|
};
|
|
|
|
float(vector pos, float scan, float char, float down) mitem_frame::item_keypress =
|
|
{
|
|
mitem ch;
|
|
float handled = FALSE;
|
|
|
|
//compensate for the frame
|
|
pos[0] += item_framesize[0];
|
|
pos[1] += item_framesize[1];
|
|
|
|
if (scan >= K_MOUSE1 && scan <= K_MOUSE5 && scan != K_MWHEELUP && scan != K_MWHEELDOWN)
|
|
{
|
|
if (item_exclusive)
|
|
ch = item_exclusive;
|
|
else
|
|
ch = item_mactivechild;
|
|
if (down) //keyboard focus follows on mouse click.
|
|
{
|
|
item_focuschange(ch, IF_KFOCUSED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ch = item_kactivechild;
|
|
if (!ch && down)
|
|
{
|
|
//if there's no key child active, then go and pick one so you can just start using keyboard access etc.
|
|
if (item_exclusive)
|
|
ch = item_exclusive;
|
|
else if (item_mactivechild)
|
|
ch = item_mactivechild;
|
|
else
|
|
{
|
|
mitem c;
|
|
for (c = item_children; c; c = c.item_next)
|
|
{
|
|
if (c.item_flags & IF_SELECTABLE)
|
|
ch = c;
|
|
}
|
|
}
|
|
if (ch)
|
|
item_focuschange(ch, IF_KFOCUSED);
|
|
ch = item_kactivechild;
|
|
}
|
|
}
|
|
|
|
if (vslider)
|
|
pos[1] -= vslider.val;
|
|
|
|
if (ch)
|
|
{
|
|
if (ch.item_keypress)
|
|
handled = ch.item_keypress(pos + ch.item_position, scan, char, down);
|
|
}
|
|
if (vslider && !handled && (scan == K_MWHEELUP || scan == K_MWHEELDOWN)) //give mwheel to the slider if its visible.
|
|
handled = vslider.item_keypress(pos + vslider.item_position, scan, char, down);
|
|
|
|
return handled;
|
|
};
|
|
void() mitem_frame::item_remove =
|
|
{
|
|
local mitem ch;
|
|
while (this.item_children)
|
|
{
|
|
ch = this.item_children;
|
|
this.item_children = ch.item_next;
|
|
ch.item_remove();
|
|
}
|
|
super::item_remove();
|
|
};
|
|
void() mitem_frame::item_resized =
|
|
{
|
|
mitem ch;
|
|
vector framemax = [item_size[0] - item_framesize[0]*2, item_size[1] - (item_framesize[1] + item_framesize[2])];
|
|
for (ch = this.item_children; ch; ch = ch.item_next)
|
|
{
|
|
vector os = ch.item_size;
|
|
mitem_parentresized(ch, framemax);
|
|
if (ch.item_resized && ch.item_size != os)
|
|
ch.item_resized();
|
|
}
|
|
item_flags |= IF_CLIENTMOVED; //make sure it happens.
|
|
|
|
super::item_resized();
|
|
};
|
|
void(vector pos) mitem_frame::item_draw =
|
|
{
|
|
local vector omin = ui.drawrectmin, omax = ui.drawrectmax;
|
|
local mitem ch;
|
|
local vector clientpos;
|
|
local vector clientsize;
|
|
|
|
if (frame_hasscroll && (item_flags & IF_CLIENTMOVED))
|
|
{
|
|
//if a client object moved, make sure the scrollbar is updated
|
|
item_flags &~= IF_CLIENTMOVED;
|
|
clientsize= '0 0';
|
|
for(ch = item_children; ch; ch = ch.item_next)
|
|
{
|
|
if (clientsize[0] < ch.item_position[0] + ch.item_size[0])
|
|
clientsize[0] = ch.item_position[0] + ch.item_size[0];
|
|
if (clientsize[1] < ch.item_position[1] + ch.item_size[1])
|
|
clientsize[1] = ch.item_position[1] + ch.item_size[1];
|
|
}
|
|
// if (clientsize[0] > item_size[0] - item_framesize[0]*2)
|
|
// //add hscroll
|
|
if (clientsize[1] > item_size[1] - (item_framesize[1]+item_framesize[2]))
|
|
{
|
|
if (!vslider)
|
|
{
|
|
local mitem_vslider tmp;
|
|
tmp = spawn(mitem_vslider, val:0, stride:8);
|
|
vslider = tmp;
|
|
}
|
|
vslider.maxv = clientsize[1] - (item_size[1] - (item_framesize[1]+item_framesize[2]));
|
|
}
|
|
else if (vslider)
|
|
{
|
|
vslider.item_remove();
|
|
vslider = (mitem_vslider)__NULL__;
|
|
}
|
|
}
|
|
else if (!frame_hasscroll && this.vslider)
|
|
{
|
|
vslider.item_remove();
|
|
vslider = (mitem_vslider)__NULL__;
|
|
}
|
|
|
|
|
|
//compensate for the frame
|
|
pos[0] += item_framesize[0];
|
|
pos[1] += item_framesize[1];
|
|
|
|
clientpos = pos;
|
|
clientsize = this.item_size;
|
|
clientsize[0] -= item_framesize[0]*2;
|
|
clientsize[1] -= (item_framesize[1]+item_framesize[2]);
|
|
|
|
if (vslider)
|
|
{
|
|
//scroll+shrink the client area to fit the slider on it.
|
|
clientpos[1] -= vslider.val;
|
|
clientsize[0] -= vslider.item_size[0];
|
|
}
|
|
|
|
|
|
if (ui.mousepos != ui.oldmousepos)
|
|
{
|
|
local mitem newfocus = __NULL__;
|
|
//if the mouse moved, select the new item
|
|
if (item_exclusive)
|
|
newfocus = item_exclusive;
|
|
else
|
|
{
|
|
for(ch = item_children; ch; ch = ch.item_next)
|
|
{
|
|
if (ch.item_flags & IF_SELECTABLE)
|
|
if (mouseinbox(clientpos + ch.item_position, ch.item_size))
|
|
{
|
|
newfocus = ch;
|
|
}
|
|
}
|
|
}
|
|
if (vslider)
|
|
if (mouseinbox(pos + [clientsize[0], 0], vslider.item_size))
|
|
newfocus = vslider;
|
|
this.item_focuschange(newfocus, IF_MFOCUSED);
|
|
}
|
|
|
|
//clip the draw rect to our area, so children don't draw outside it. don't draw if its inverted.
|
|
if (pos_x > ui.drawrectmin[0])
|
|
ui.drawrectmin[0] = pos_x;
|
|
if (pos_y > ui.drawrectmin[1])
|
|
ui.drawrectmin[1] = pos_y;
|
|
if (pos_x+clientsize_x < ui.drawrectmax[0])
|
|
ui.drawrectmax[0] = pos_x+clientsize_x;
|
|
if (pos_y+clientsize_y < ui.drawrectmax[1])
|
|
ui.drawrectmax[1] = pos_y+clientsize[1];
|
|
if (ui.drawrectmax[0] > ui.drawrectmin[0] && ui.drawrectmax[1] > ui.drawrectmin[1])
|
|
{
|
|
ui.setcliparea(ui.drawrectmin[0], ui.drawrectmin[1], ui.drawrectmax[0] - ui.drawrectmin[0], ui.drawrectmax[1] - ui.drawrectmin[1]);
|
|
if (item_exclusive)
|
|
item_exclusive.item_draw(clientpos + ch.item_position);
|
|
else
|
|
{
|
|
for(ch = item_children; ch; ch = ch.item_next)
|
|
{
|
|
if not (ch.item_flags & IF_INVISIBLE)
|
|
ch.item_draw(clientpos + ch.item_position);
|
|
}
|
|
}
|
|
ui.setcliparea(omin_x, omin_y, omax_x - omin_x, omax_y - omin_y);
|
|
|
|
if (vslider)
|
|
{
|
|
vslider.item_size[1] = clientsize[1];
|
|
vslider.item_draw(pos + [clientsize[0], 0]);
|
|
}
|
|
}
|
|
ui.drawrectmin = omin;
|
|
ui.drawrectmax = omax;
|
|
};
|
|
#define menuitemframe_spawn(sz) spawn(mitem_frame, item_size:sz)
|
|
|
|
#endif //MITEM_FRAME_QC__
|