From 861e3ffb66df50d7eb9be7c5947fd3897981082e Mon Sep 17 00:00:00 2001 From: TimePath Date: Sun, 11 Dec 2016 17:44:01 +1100 Subject: [PATCH] Menu: ScrollPanel component --- qcsrc/menu/draw.qc | 53 +++++++++++++------ qcsrc/menu/item.qc | 4 +- qcsrc/menu/item.qh | 2 +- qcsrc/menu/item/button.qc | 6 +-- qcsrc/menu/item/button.qh | 2 +- qcsrc/menu/item/container.qc | 14 +++-- qcsrc/menu/item/container.qh | 2 +- qcsrc/menu/item/image.qc | 5 +- qcsrc/menu/item/inputbox.qc | 16 +++--- qcsrc/menu/item/inputbox.qh | 2 +- qcsrc/menu/item/inputcontainer.qc | 12 ++--- qcsrc/menu/item/inputcontainer.qh | 2 +- qcsrc/menu/item/listbox.qc | 60 +++++++++++----------- qcsrc/menu/item/listbox.qh | 2 +- qcsrc/menu/item/nexposee.qc | 30 +++++------ qcsrc/menu/item/nexposee.qh | 2 +- qcsrc/menu/item/slider.qc | 56 ++++++++++---------- qcsrc/menu/item/slider.qh | 2 +- qcsrc/menu/xonotic/_mod.inc | 1 + qcsrc/menu/xonotic/_mod.qh | 1 + qcsrc/menu/xonotic/colorpicker.qc | 6 +-- qcsrc/menu/xonotic/colorpicker.qh | 2 +- qcsrc/menu/xonotic/colorpicker_string.qc | 6 +-- qcsrc/menu/xonotic/colorpicker_string.qh | 2 +- qcsrc/menu/xonotic/dialog_settings_game.qc | 5 +- qcsrc/menu/xonotic/dialog_settings_game.qh | 3 +- qcsrc/menu/xonotic/picker.qc | 12 ++--- qcsrc/menu/xonotic/picker.qh | 2 +- qcsrc/menu/xonotic/screenshotimage.qc | 4 +- qcsrc/menu/xonotic/screenshotimage.qh | 2 +- qcsrc/menu/xonotic/scrollpanel.qc | 46 +++++++++++++++++ qcsrc/menu/xonotic/scrollpanel.qh | 24 +++++++++ 32 files changed, 242 insertions(+), 146 deletions(-) create mode 100644 qcsrc/menu/xonotic/scrollpanel.qc create mode 100644 qcsrc/menu/xonotic/scrollpanel.qh diff --git a/qcsrc/menu/draw.qc b/qcsrc/menu/draw.qc index 01184a4bf..ae6967e36 100644 --- a/qcsrc/menu/draw.qc +++ b/qcsrc/menu/draw.qc @@ -312,32 +312,55 @@ float draw_CondensedFontFactor(string theText, float ICanHasKallerz, vector Size return 1.0; } -float draw_clipSet; +IntrusiveList draw_clip; +STATIC_INIT(draw_clip) { draw_clip = IL_NEW(); } +CLASS(ClipFrame, Object) + ATTRIB(ClipFrame, clip_shift, vector, '0 0 0'); + ATTRIB(ClipFrame, clip_scale, vector, '0 0 0'); +ENDCLASS(ClipFrame) + +void _draw_SetClip(vector o, vector s) +{ + ClipFrame prev = IL_PEEK(draw_clip); + if (prev) { + o.x = bound(prev.clip_shift.x, o.x, prev.clip_shift.x + prev.clip_scale.x); + o.y = bound(prev.clip_shift.y, o.y, prev.clip_shift.y + prev.clip_scale.y); + s.x = bound(0, s.x, prev.clip_scale.x - (o.x - prev.clip_shift.x)); + s.y = bound(0, s.y, prev.clip_scale.y - (o.y - prev.clip_shift.y)); + } + ClipFrame e = NEW(ClipFrame); + e.clip_shift = o; + e.clip_scale = s; + IL_PUSH(draw_clip, e); + drawsetcliparea(o.x, o.y, s.x, s.y); +} + void draw_SetClip() { - if(draw_clipSet) - error("Already clipping, no stack implemented here, sorry"); - drawsetcliparea(draw_shift.x, draw_shift.y, draw_scale.x, draw_scale.y); - draw_clipSet = 1; + _draw_SetClip(draw_shift, draw_scale); } void draw_SetClipRect(vector theOrigin, vector theScale) { - vector o, s; - if(draw_clipSet) - error("Already clipping, no stack implemented here, sorry"); - o = boxToGlobal(theOrigin, draw_shift, draw_scale); - s = boxToGlobalSize(theScale, draw_scale); - drawsetcliparea(o.x, o.y, s.x, s.y); - draw_clipSet = 1; + _draw_SetClip( + boxToGlobal(theOrigin, draw_shift, draw_scale), + boxToGlobalSize(theScale, draw_scale) + ); } void draw_ClearClip() { - if(!draw_clipSet) - error("Not clipping, can't clear it then"); + if (IL_EMPTY(draw_clip)) { + LOG_FATAL("Not clipping, can't clear it then"); + } + entity currentSettings = IL_PEEK(draw_clip); + IL_REMOVE(draw_clip, currentSettings); + delete(currentSettings); drawresetcliparea(); - draw_clipSet = 0; + ClipFrame e = IL_PEEK(draw_clip); + if (e) { + drawsetcliparea(e.clip_shift.x, e.clip_shift.y, e.clip_scale.x, e.clip_scale.y); + } } string draw_TextShortenToWidth(string theText, float maxWidth, float ICanHasKallerz, vector SizeThxBye) diff --git a/qcsrc/menu/item.qc b/qcsrc/menu/item.qc index 1d31e95a9..a5c7cfa85 100644 --- a/qcsrc/menu/item.qc +++ b/qcsrc/menu/item.qc @@ -74,9 +74,9 @@ return 0; // unhandled } - METHOD(Item, mousePress, float(Item this, vector pos)) + METHOD(Item, mousePress, bool(Item this, vector pos)) { - return 0; // unhandled + return false; // unhandled } METHOD(Item, mouseDrag, float(Item this, vector pos)) diff --git a/qcsrc/menu/item.qh b/qcsrc/menu/item.qh index 00dae2ed3..457da8d67 100644 --- a/qcsrc/menu/item.qh +++ b/qcsrc/menu/item.qh @@ -8,7 +8,7 @@ CLASS(Item, Object) METHOD(Item, keyDown, float(Item, float, float, float)); METHOD(Item, keyUp, float(Item, float, float, float)); METHOD(Item, mouseMove, float(Item, vector)); - METHOD(Item, mousePress, float(Item, vector)); + METHOD(Item, mousePress, bool(Item this, vector pos)); METHOD(Item, mouseDrag, float(Item, vector)); METHOD(Item, mouseRelease, float(Item, vector)); METHOD(Item, focusEnter, void(Item)); diff --git a/qcsrc/menu/item/button.qc b/qcsrc/menu/item/button.qc index 8299a6859..77e4ccad2 100644 --- a/qcsrc/menu/item/button.qc +++ b/qcsrc/menu/item/button.qc @@ -36,10 +36,10 @@ if (pos.y >= 1) me.pressed = 0; return 1; } - float Button_mousePress(entity me, vector pos) + METHOD(Button, mousePress, bool(Button this, vector pos)) { - me.mouseDrag(me, pos); // verify coordinates - return 1; + this.mouseDrag(this, pos); // verify coordinates + return true; } float Button_mouseRelease(entity me, vector pos) { diff --git a/qcsrc/menu/item/button.qh b/qcsrc/menu/item/button.qh index 1a164245c..2077da700 100644 --- a/qcsrc/menu/item/button.qh +++ b/qcsrc/menu/item/button.qh @@ -9,7 +9,7 @@ CLASS(Button, Label) METHOD(Button, showNotify, void(entity)); METHOD(Button, resizeNotify, void(entity, vector, vector, vector, vector)); METHOD(Button, keyDown, float(entity, float, float, float)); - METHOD(Button, mousePress, float(entity, vector)); + METHOD(Button, mousePress, bool(Button this, vector pos)); METHOD(Button, mouseDrag, float(entity, vector)); METHOD(Button, mouseRelease, float(entity, vector)); METHOD(Button, playClickSound, void(entity)); diff --git a/qcsrc/menu/item/container.qc b/qcsrc/menu/item/container.qc index 56535bf71..04e1bc6f7 100644 --- a/qcsrc/menu/item/container.qc +++ b/qcsrc/menu/item/container.qc @@ -178,19 +178,17 @@ } return 0; } - float Container_mousePress(entity me, vector pos) + METHOD(Container, mousePress, bool(Container this, vector pos)) { - entity f; - float r; - f = me.focusedChild; + entity f = this.focusedChild; if (f) { - me.enterSubitem(me, f); - r = f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size)); - me.leaveSubitem(me); + this.enterSubitem(this, f); + bool r = f.mousePress(f, globalToBox(pos, f.Container_origin, f.Container_size)); + this.leaveSubitem(this); return r; } - return 0; + return false; } float Container_mouseDrag(entity me, vector pos) { diff --git a/qcsrc/menu/item/container.qh b/qcsrc/menu/item/container.qh index 8273f5ddd..b73752685 100644 --- a/qcsrc/menu/item/container.qh +++ b/qcsrc/menu/item/container.qh @@ -7,7 +7,7 @@ CLASS(Container, Item) METHOD(Container, keyUp, float(entity, float, float, float)); METHOD(Container, keyDown, float(entity, float, float, float)); METHOD(Container, mouseMove, float(entity, vector)); - METHOD(Container, mousePress, float(entity, vector)); + METHOD(Container, mousePress, bool(Container this, vector pos)); METHOD(Container, mouseDrag, float(entity, vector)); METHOD(Container, mouseRelease, float(entity, vector)); METHOD(Container, focusLeave, void(entity)); diff --git a/qcsrc/menu/item/image.qc b/qcsrc/menu/item/image.qc index 59405ec16..73b302c4a 100644 --- a/qcsrc/menu/item/image.qc +++ b/qcsrc/menu/item/image.qc @@ -18,9 +18,10 @@ void Image_draw(entity me) { - if (me.imgSize.x > 1 || me.imgSize.y > 1) draw_SetClip(); + bool willClip = me.imgSize.x > 1 || me.imgSize.y > 1; + if (willClip) draw_SetClip(); draw_Picture(me.imgOrigin, me.src, me.imgSize, me.color, 1); - if (me.imgSize.x > 1 || me.imgSize.y > 1) draw_ClearClip(); + if (willClip) draw_ClearClip(); SUPER(Image).draw(me); } void Image_updateAspect(entity me) diff --git a/qcsrc/menu/item/inputbox.qc b/qcsrc/menu/item/inputbox.qc index 6f7ed9f24..a418dc2ce 100644 --- a/qcsrc/menu/item/inputbox.qc +++ b/qcsrc/menu/item/inputbox.qc @@ -71,17 +71,17 @@ return 1; } - float InputBox_mousePress(entity me, vector pos) + METHOD(InputBox, mousePress, bool(InputBox this, vector pos)) { - if (me.enableClearButton) - if (over_ClearButton(me, pos)) + if (this.enableClearButton) + if (over_ClearButton(this, pos)) { - me.cb_pressed = 1; - return 1; + this.cb_pressed = 1; + return true; } - me.dragScrollTimer = time; - me.pressed = 1; - return InputBox_mouseDrag(me, pos); + this.dragScrollTimer = time; + this.pressed = 1; + return InputBox_mouseDrag(this, pos); } float InputBox_mouseRelease(entity me, vector pos) diff --git a/qcsrc/menu/item/inputbox.qh b/qcsrc/menu/item/inputbox.qh index e3eede653..5b0c28f9e 100644 --- a/qcsrc/menu/item/inputbox.qh +++ b/qcsrc/menu/item/inputbox.qh @@ -9,7 +9,7 @@ CLASS(InputBox, Label) METHOD(InputBox, keyDown, float(entity, float, float, float)); METHOD(InputBox, mouseMove, float(entity, vector)); METHOD(InputBox, mouseRelease, float(entity, vector)); - METHOD(InputBox, mousePress, float(entity, vector)); + METHOD(InputBox, mousePress, bool(InputBox this, vector pos)); METHOD(InputBox, mouseDrag, float(entity, vector)); METHOD(InputBox, showNotify, void(entity)); METHOD(InputBox, resizeNotify, void(entity, vector, vector, vector, vector)); diff --git a/qcsrc/menu/item/inputcontainer.qc b/qcsrc/menu/item/inputcontainer.qc index 37c46240f..641e47745 100644 --- a/qcsrc/menu/item/inputcontainer.qc +++ b/qcsrc/menu/item/inputcontainer.qc @@ -117,13 +117,13 @@ if (pos.x >= 0 && pos.y >= 0 && pos.x < 1 && pos.y < 1) return 1; return 0; } - float InputContainer_mousePress(entity me, vector pos) + METHOD(InputContainer, mousePress, bool(InputContainer this, vector pos)) { - me.mouseFocusedChild = NULL; // force focusing - if (me._changeFocusXY(me, pos)) - if (SUPER(InputContainer).mousePress(me, pos)) return 1; - if (pos.x >= 0 && pos.y >= 0 && pos.x < 1 && pos.y < 1) return 1; - return 0; + this.mouseFocusedChild = NULL; // force focusing + if (this._changeFocusXY(this, pos)) + if (SUPER(InputContainer).mousePress(this, pos)) return true; + if (pos.x >= 0 && pos.y >= 0 && pos.x < 1 && pos.y < 1) return true; + return false; } float InputContainer_mouseRelease(entity me, vector pos) { diff --git a/qcsrc/menu/item/inputcontainer.qh b/qcsrc/menu/item/inputcontainer.qh index 9ae4a5375..8ded2e657 100644 --- a/qcsrc/menu/item/inputcontainer.qh +++ b/qcsrc/menu/item/inputcontainer.qh @@ -4,7 +4,7 @@ CLASS(InputContainer, Container) METHOD(InputContainer, keyDown, float(entity, float, float, float)); METHOD(InputContainer, mouseMove, float(entity, vector)); - METHOD(InputContainer, mousePress, float(entity, vector)); + METHOD(InputContainer, mousePress, bool(InputContainer this, vector pos)); METHOD(InputContainer, mouseRelease, float(entity, vector)); METHOD(InputContainer, mouseDrag, float(entity, vector)); METHOD(InputContainer, focusLeave, void(entity)); diff --git a/qcsrc/menu/item/listbox.qc b/qcsrc/menu/item/listbox.qc index aa10c20b3..07385e91e 100644 --- a/qcsrc/menu/item/listbox.qc +++ b/qcsrc/menu/item/listbox.qc @@ -208,43 +208,43 @@ } return 1; } - float ListBox_mousePress(entity me, vector pos) + METHOD(ListBox, mousePress, bool(ListBox this, vector pos)) { - if (pos.x < 0) return 0; - if (pos.y < 0) return 0; - if (pos.x >= 1) return 0; - if (pos.y >= 1) return 0; - me.dragScrollPos = pos; - me.updateControlTopBottom(me); - if (pos.x >= 1 - me.controlWidth) + if (pos.x < 0) return false; + if (pos.y < 0) return false; + if (pos.x >= 1) return false; + if (pos.y >= 1) return false; + this.dragScrollPos = pos; + this.updateControlTopBottom(this); + if (pos.x >= 1 - this.controlWidth) { - // if hit, set me.pressed, otherwise scroll by one page - if (pos.y < me.controlTop) + // if hit, set this.pressed, otherwise scroll by one page + if (pos.y < this.controlTop) { // page up - me.scrollPosTarget = max(me.scrollPosTarget - 1, 0); + this.scrollPosTarget = max(this.scrollPosTarget - 1, 0); } - else if (pos.y > me.controlBottom) + else if (pos.y > this.controlBottom) { // page down - me.scrollPosTarget = min(me.scrollPosTarget + 1, me.getTotalHeight(me) - 1); + this.scrollPosTarget = min(this.scrollPosTarget + 1, this.getTotalHeight(this) - 1); } else { - me.pressed = 1; - me.pressOffset = pos.y; - me.previousValue = me.scrollPos; + this.pressed = 1; + this.pressOffset = pos.y; + this.previousValue = this.scrollPos; } } else { // continue doing that while dragging (even when dragging outside). When releasing, forward the click to the then selected item. - me.pressed = 2; + this.pressed = 2; // an item has been clicked. Select it, ... - me.setSelected(me, me.getItemAtPos(me, me.scrollPos + pos.y)); - me.setFocusedItem(me, me.selectedItem); + this.setSelected(this, this.getItemAtPos(this, this.scrollPos + pos.y)); + this.setFocusedItem(this, this.selectedItem); } - return 1; + return true; } void ListBox_setFocusedItem(entity me, int item) { @@ -335,9 +335,7 @@ AUTOCVAR(menu_scroll_averaging_time_pressed, float, 0.06, "smooth scroll averaging time when dragging the scrollbar"); void ListBox_draw(entity me) { - float i; - vector absSize, fillSize = '0 0 0'; - vector oldshift, oldscale; + vector fillSize = '0 0 0'; // we can't do this in mouseMove as the list can scroll without moving the cursor if (me.mouseMoveOffset != -1) me.setFocusedItem(me, me.getItemAtPos(me, me.scrollPos + me.mouseMoveOffset)); @@ -376,19 +374,19 @@ } } draw_SetClip(); - oldshift = draw_shift; - oldscale = draw_scale; + vector oldshift = draw_shift; + vector oldscale = draw_scale; - i = me.getItemAtPos(me, me.scrollPos); - float j = me.getItemStart(me, i) - me.scrollPos; - for ( ; i < me.nItems && j < 1; ++i) + int i = me.getItemAtPos(me, me.scrollPos); + float y = me.getItemStart(me, i) - me.scrollPos; + for ( ; i < me.nItems && y < 1; ++i) { - draw_shift = boxToGlobal(eY * j, oldshift, oldscale); + draw_shift = boxToGlobal(eY * y, oldshift, oldscale); vector relSize = eX * (1 - me.controlWidth) + eY * me.getItemHeight(me, i); - absSize = boxToGlobalSize(relSize, me.size); + vector absSize = boxToGlobalSize(relSize, me.size); draw_scale = boxToGlobalSize(relSize, oldscale); me.drawListBoxItem(me, i, absSize, (me.selectedItem == i), (me.focusedItem == i)); - j += relSize.y; + y += relSize.y; } draw_ClearClip(); diff --git a/qcsrc/menu/item/listbox.qh b/qcsrc/menu/item/listbox.qh index 56fda91cc..b3f5164a4 100644 --- a/qcsrc/menu/item/listbox.qh +++ b/qcsrc/menu/item/listbox.qh @@ -7,7 +7,7 @@ CLASS(ListBox, Item) METHOD(ListBox, draw, void(entity)); METHOD(ListBox, keyDown, float(entity, float, float, float)); METHOD(ListBox, mouseMove, float(entity, vector)); - METHOD(ListBox, mousePress, float(entity, vector)); + METHOD(ListBox, mousePress, bool(ListBox this, vector pos)); METHOD(ListBox, mouseDrag, float(entity, vector)); METHOD(ListBox, mouseRelease, float(entity, vector)); METHOD(ListBox, focusLeave, void(entity)); diff --git a/qcsrc/menu/item/nexposee.qc b/qcsrc/menu/item/nexposee.qc index c0f18cf85..d42fceb53 100644 --- a/qcsrc/menu/item/nexposee.qc +++ b/qcsrc/menu/item/nexposee.qc @@ -154,35 +154,35 @@ LABEL(have_overlap) SUPER(Nexposee).draw(me); } - float Nexposee_mousePress(entity me, vector pos) + METHOD(Nexposee, mousePress, bool(Nexposee this, vector pos)) { - if (me.animationState == 0) + if (this.animationState == 0) { - me.mouseFocusedChild = NULL; - Nexposee_mouseMove(me, pos); - if (me.mouseFocusedChild) + this.mouseFocusedChild = NULL; + Nexposee_mouseMove(this, pos); + if (this.mouseFocusedChild) { m_play_click_sound(MENU_SOUND_OPEN); - me.animationState = 1; - SUPER(Nexposee).setFocus(me, NULL); + this.animationState = 1; + SUPER(Nexposee).setFocus(this, NULL); } else { - me.close(me); + this.close(this); } - return 1; + return true; } - else if (me.animationState == 2) + else if (this.animationState == 2) { - if (!(SUPER(Nexposee).mousePress(me, pos))) + if (!(SUPER(Nexposee).mousePress(this, pos))) { m_play_click_sound(MENU_SOUND_CLOSE); - me.animationState = 3; - SUPER(Nexposee).setFocus(me, NULL); + this.animationState = 3; + SUPER(Nexposee).setFocus(this, NULL); } - return 1; + return true; } - return 0; + return false; } float Nexposee_mouseRelease(entity me, vector pos) diff --git a/qcsrc/menu/item/nexposee.qh b/qcsrc/menu/item/nexposee.qh index 4159648f9..440413b5e 100644 --- a/qcsrc/menu/item/nexposee.qh +++ b/qcsrc/menu/item/nexposee.qh @@ -5,7 +5,7 @@ CLASS(Nexposee, Container) METHOD(Nexposee, draw, void(entity)); METHOD(Nexposee, keyDown, float(entity, float, float, float)); METHOD(Nexposee, keyUp, float(entity, float, float, float)); - METHOD(Nexposee, mousePress, float(entity, vector)); + METHOD(Nexposee, mousePress, bool(Nexposee this, vector pos)); METHOD(Nexposee, mouseMove, float(entity, vector)); METHOD(Nexposee, mouseRelease, float(entity, vector)); METHOD(Nexposee, mouseDrag, float(entity, vector)); diff --git a/qcsrc/menu/item/slider.qc b/qcsrc/menu/item/slider.qc index 2e89bb68e..b569c3b0c 100644 --- a/qcsrc/menu/item/slider.qc +++ b/qcsrc/menu/item/slider.qc @@ -172,53 +172,53 @@ return 1; } - float Slider_mousePress(entity me, vector pos) + METHOD(Slider, mousePress, bool(Slider this, vector pos)) { float controlCenter; - if (me.disabled) return 0; - if (pos.x < 0) return 0; - if (pos.y < 0) return 0; - if (pos.x >= 1 - me.textSpace) return 0; - if (pos.y >= 1) return 0; - controlCenter = (me.value - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth) + 0.5 * me.controlWidth; - if (fabs(pos.x - controlCenter) <= 0.5 * me.controlWidth) + if (this.disabled) return false; + if (pos.x < 0) return false; + if (pos.y < 0) return false; + if (pos.x >= 1 - this.textSpace) return false; + if (pos.y >= 1) return false; + controlCenter = (this.value - this.valueMin) / (this.valueMax - this.valueMin) * (1 - this.textSpace - this.controlWidth) + 0.5 * this.controlWidth; + if (fabs(pos.x - controlCenter) <= 0.5 * this.controlWidth) { - me.pressed = 1; - me.pressOffset = pos.x - controlCenter; - me.previousValue = me.value; - // me.mouseDrag(me, pos); + this.pressed = 1; + this.pressOffset = pos.x - controlCenter; + this.previousValue = this.value; + // this.mouseDrag(this, pos); } else { float clickValue, pageValue, inRange; - clickValue = median(0, (pos.x - me.pressOffset - 0.5 * me.controlWidth) / (1 - me.textSpace - me.controlWidth), 1) * (me.valueMax - me.valueMin) + me.valueMin; - inRange = (almost_in_bounds(me.valueMin, me.value, me.valueMax)); + clickValue = median(0, (pos.x - this.pressOffset - 0.5 * this.controlWidth) / (1 - this.textSpace - this.controlWidth), 1) * (this.valueMax - this.valueMin) + this.valueMin; + inRange = (almost_in_bounds(this.valueMin, this.value, this.valueMax)); if (pos.x < controlCenter) { - pageValue = me.value - me.valuePageStep; - if (me.valueStep) clickValue = floor(clickValue / me.valueStep) * me.valueStep; + pageValue = this.value - this.valuePageStep; + if (this.valueStep) clickValue = floor(clickValue / this.valueStep) * this.valueStep; pageValue = max(pageValue, clickValue); } else { - pageValue = me.value + me.valuePageStep; - if (me.valueStep) clickValue = ceil(clickValue / me.valueStep) * me.valueStep; + pageValue = this.value + this.valuePageStep; + if (this.valueStep) clickValue = ceil(clickValue / this.valueStep) * this.valueStep; pageValue = min(pageValue, clickValue); } - if (inRange) me.setValue(me, median(me.valueMin, pageValue, me.valueMax)); - else me.setValue(me, me.valueMax); - if(me.applyButton) - me.applyButton.disabled = false; + if (inRange) this.setValue(this, median(this.valueMin, pageValue, this.valueMax)); + else this.setValue(this, this.valueMax); + if(this.applyButton) + this.applyButton.disabled = false; if (pageValue == clickValue) { - controlCenter = (me.value - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth) + 0.5 * me.controlWidth; - me.pressed = 1; - me.pressOffset = pos.x - controlCenter; - me.previousValue = me.value; - // me.mouseDrag(me, pos); + controlCenter = (this.value - this.valueMin) / (this.valueMax - this.valueMin) * (1 - this.textSpace - this.controlWidth) + 0.5 * this.controlWidth; + this.pressed = 1; + this.pressOffset = pos.x - controlCenter; + this.previousValue = this.value; + // this.mouseDrag(this, pos); } } - return 1; + return true; } float Slider_mouseRelease(entity me, vector pos) { diff --git a/qcsrc/menu/item/slider.qh b/qcsrc/menu/item/slider.qh index 3b7327788..c798aae33 100644 --- a/qcsrc/menu/item/slider.qh +++ b/qcsrc/menu/item/slider.qh @@ -10,7 +10,7 @@ CLASS(Slider, Label) METHOD(Slider, draw, void(entity)); METHOD(Slider, keyDown, float(entity, float, float, float)); METHOD(Slider, keyUp, float(entity, float, float, float)); - METHOD(Slider, mousePress, float(entity, vector)); + METHOD(Slider, mousePress, bool(Slider this, vector pos)); METHOD(Slider, mouseDrag, float(entity, vector)); METHOD(Slider, mouseRelease, float(entity, vector)); METHOD(Slider, valueToText, string(entity, float)); diff --git a/qcsrc/menu/xonotic/_mod.inc b/qcsrc/menu/xonotic/_mod.inc index 577c82258..fd8371828 100644 --- a/qcsrc/menu/xonotic/_mod.inc +++ b/qcsrc/menu/xonotic/_mod.inc @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/_mod.qh b/qcsrc/menu/xonotic/_mod.qh index b6e34eff2..f1644a2f5 100644 --- a/qcsrc/menu/xonotic/_mod.qh +++ b/qcsrc/menu/xonotic/_mod.qh @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/colorpicker.qc b/qcsrc/menu/xonotic/colorpicker.qc index 357276e16..d8aedf695 100644 --- a/qcsrc/menu/xonotic/colorpicker.qc +++ b/qcsrc/menu/xonotic/colorpicker.qc @@ -16,10 +16,10 @@ void XonoticColorpicker_configureXonoticColorpicker(entity me, entity theTextbox me.configureImage(me, me.image); } -float XonoticColorpicker_mousePress(entity me, vector coords) +METHOD(XonoticColorpicker, mousePress, bool(XonoticColorpicker this, vector pos)) { - me.mouseDrag(me, coords); - return 1; + this.mouseDrag(this, pos); + return true; } // must match hslimage.c diff --git a/qcsrc/menu/xonotic/colorpicker.qh b/qcsrc/menu/xonotic/colorpicker.qh index b1c9d1e80..149357dd9 100644 --- a/qcsrc/menu/xonotic/colorpicker.qh +++ b/qcsrc/menu/xonotic/colorpicker.qh @@ -3,7 +3,7 @@ #include "../item/image.qh" CLASS(XonoticColorpicker, Image) METHOD(XonoticColorpicker, configureXonoticColorpicker, void(entity, entity)); - METHOD(XonoticColorpicker, mousePress, float(entity, vector)); + METHOD(XonoticColorpicker, mousePress, bool(XonoticColorpicker this, vector pos)); METHOD(XonoticColorpicker, mouseRelease, float(entity, vector)); METHOD(XonoticColorpicker, mouseDrag, float(entity, vector)); ATTRIB(XonoticColorpicker, controlledTextbox, entity); diff --git a/qcsrc/menu/xonotic/colorpicker_string.qc b/qcsrc/menu/xonotic/colorpicker_string.qc index 200204c00..5a44e5883 100644 --- a/qcsrc/menu/xonotic/colorpicker_string.qc +++ b/qcsrc/menu/xonotic/colorpicker_string.qc @@ -50,10 +50,10 @@ void XonoticColorpickerString_saveCvars(entity me) cvar_set(me.cvarName, sprintf("%v", hslimage_color(me.prevcoords, me.imagemargin))); } -float XonoticColorpickerString_mousePress(entity me, vector coords) +METHOD(XonoticColorpickerString, mousePress, bool(XonoticColorpickerString this, vector pos)) { - me.mouseDrag(me, coords); - return 1; + this.mouseDrag(this, pos); + return true; } float XonoticColorpickerString_mouseDrag(entity me, vector coords) diff --git a/qcsrc/menu/xonotic/colorpicker_string.qh b/qcsrc/menu/xonotic/colorpicker_string.qh index e990234b3..aa4a10c93 100644 --- a/qcsrc/menu/xonotic/colorpicker_string.qh +++ b/qcsrc/menu/xonotic/colorpicker_string.qh @@ -5,7 +5,7 @@ #include "../item/image.qh" CLASS(XonoticColorpickerString, Image) METHOD(XonoticColorpickerString, configureXonoticColorpickerString, void(entity, string, string)); - METHOD(XonoticColorpickerString, mousePress, float(entity, vector)); + METHOD(XonoticColorpickerString, mousePress, bool(XonoticColorpickerString this, vector pos)); METHOD(XonoticColorpickerString, mouseRelease, float(entity, vector)); METHOD(XonoticColorpickerString, mouseDrag, float(entity, vector)); diff --git a/qcsrc/menu/xonotic/dialog_settings_game.qc b/qcsrc/menu/xonotic/dialog_settings_game.qc index d2ce368d1..87134cb78 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game.qc +++ b/qcsrc/menu/xonotic/dialog_settings_game.qc @@ -94,7 +94,9 @@ CONSTRUCTOR(XonoticRegisteredSettingsList, DataSource _source) { METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this)) { - entity c = this.currentPanel; + entity s = this.currentPanel; + s.viewportHeight = 15.5; + entity c = s.currentPanel; entity removing = this.currentItem; DataSource data = this.topicList.source; entity adding = data.getEntry(data, this.topicList.selectedItem, func_null); @@ -107,6 +109,7 @@ METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this)) this.currentItem = adding; adding.resizeNotify(adding, '0 0 0', c.size, '0 0 0', c.size); c.addItem(c, adding, '0 0 0', '1 1 0', 1); + s.resizeNotify(s, '0 0 0', s.size, '0 0 0', s.size); } } METHOD(XonoticGameSettingsTab, fill, void(entity this)) diff --git a/qcsrc/menu/xonotic/dialog_settings_game.qh b/qcsrc/menu/xonotic/dialog_settings_game.qh index b9231642b..c9617f582 100644 --- a/qcsrc/menu/xonotic/dialog_settings_game.qh +++ b/qcsrc/menu/xonotic/dialog_settings_game.qh @@ -32,13 +32,14 @@ CLASS(XonoticRegisteredSettingsList, XonoticListBox) ENDCLASS(XonoticRegisteredSettingsList) #include "tab.qh" +#include "scrollpanel.qh" CLASS(XonoticGameSettingsTab, XonoticTab) ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9); ATTRIB(XonoticGameSettingsTab, rows, float, 15.5); ATTRIB(XonoticGameSettingsTab, columns, float, 6.5); ATTRIB(XonoticGameSettingsTab, source, DataSource, NEW(SettingSource)); ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, this.source)); - ATTRIB(XonoticGameSettingsTab, currentPanel, entity, NEW(XonoticTab)); + ATTRIB(XonoticGameSettingsTab, currentPanel, entity, NEW(XonoticScrollPanel)); ATTRIB(XonoticGameSettingsTab, currentItem, entity); METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this)); METHOD(XonoticGameSettingsTab, fill, void(entity this)); diff --git a/qcsrc/menu/xonotic/picker.qc b/qcsrc/menu/xonotic/picker.qc index db302e9a8..527697683 100644 --- a/qcsrc/menu/xonotic/picker.qc +++ b/qcsrc/menu/xonotic/picker.qc @@ -39,17 +39,17 @@ float XonoticPicker_mouseDrag(entity me, vector coords) return me.mouseMove(me, coords); } -float XonoticPicker_mousePress(entity me, vector coords) +METHOD(XonoticPicker, mousePress, bool(XonoticPicker this, vector pos)) { - me.mouseMove(me, coords); + this.mouseMove(this, pos); - if(me.focusedCell.x >= 0) + if(this.focusedCell.x >= 0) { - me.pressed = 1; - me.pressedCell = me.focusedCell; + this.pressed = 1; + this.pressedCell = this.focusedCell; } - return 1; + return true; } float XonoticPicker_mouseRelease(entity me, vector coords) diff --git a/qcsrc/menu/xonotic/picker.qh b/qcsrc/menu/xonotic/picker.qh index b8e19cf19..c98e9fc9b 100644 --- a/qcsrc/menu/xonotic/picker.qh +++ b/qcsrc/menu/xonotic/picker.qh @@ -3,7 +3,7 @@ #include "../item.qh" CLASS(XonoticPicker, Item) METHOD(XonoticPicker, configureXonoticPicker, void(entity)); - METHOD(XonoticPicker, mousePress, float(entity, vector)); + METHOD(XonoticPicker, mousePress, bool(XonoticPicker this, vector pos)); METHOD(XonoticPicker, mouseRelease, float(entity, vector)); METHOD(XonoticPicker, mouseMove, float(entity, vector)); METHOD(XonoticPicker, mouseDrag, float(entity, vector)); diff --git a/qcsrc/menu/xonotic/screenshotimage.qc b/qcsrc/menu/xonotic/screenshotimage.qc index 42e168b4b..8e8f3ccf7 100644 --- a/qcsrc/menu/xonotic/screenshotimage.qc +++ b/qcsrc/menu/xonotic/screenshotimage.qc @@ -27,9 +27,9 @@ void XonoticScreenshotImage_load(entity me, string theImage) me.setZoom(me, 0, 0); } -float XonoticScreenshotImage_mousePress(entity me, vector coords) +METHOD(XonoticScreenshotImage, mousePress, bool(XonoticScreenshotImage this, vector pos)) { - return me.drag_setStartPos(me, coords); + return this.drag_setStartPos(this, pos); } float XonoticScreenshotImage_mouseDrag(entity me, vector coords) diff --git a/qcsrc/menu/xonotic/screenshotimage.qh b/qcsrc/menu/xonotic/screenshotimage.qh index 8920bed28..c27a85337 100644 --- a/qcsrc/menu/xonotic/screenshotimage.qh +++ b/qcsrc/menu/xonotic/screenshotimage.qh @@ -6,7 +6,7 @@ CLASS(XonoticScreenshotImage, XonoticImage) METHOD(XonoticScreenshotImage, load, void(entity, string)); METHOD(XonoticScreenshotImage, draw, void(entity)); ATTRIB(XonoticScreenshotImage, focusable, float, 1); // mousePress and mouseDrag work only if focusable is set - METHOD(XonoticScreenshotImage, mousePress, float(entity, vector)); + METHOD(XonoticScreenshotImage, mousePress, bool(XonoticScreenshotImage this, vector pos)); METHOD(XonoticScreenshotImage, mouseDrag, float(entity, vector)); METHOD(XonoticScreenshotImage, mouseMove, float(entity, vector)); METHOD(XonoticScreenshotImage, resizeNotify, void(entity, vector, vector, vector, vector)); diff --git a/qcsrc/menu/xonotic/scrollpanel.qc b/qcsrc/menu/xonotic/scrollpanel.qc new file mode 100644 index 000000000..874a0aff1 --- /dev/null +++ b/qcsrc/menu/xonotic/scrollpanel.qc @@ -0,0 +1,46 @@ +#include "scrollpanel.qh" + +METHOD(XonoticScrollPanel, drawListBoxItem, void(XonoticScrollPanel this, int i, vector absSize, bool isSelected, bool isFocused)) +{ + XonoticTab p = this.currentPanel; + p.draw(p); +} + +METHOD(XonoticScrollPanel, resizeNotify, void(XonoticScrollPanel this, vector relOrigin, vector relSize, vector absOrigin, vector absSize)) +{ + SUPER(XonoticScrollPanel).resizeNotify(this, relOrigin, relSize, absOrigin, absSize); + this.scrollToItem(this, 0); + XonoticTab p = this.currentPanel; + float m = p.firstChild.rows / this.viewportHeight; + this.itemHeight = m; + relSize.y *= m; + absSize.y *= m; + p.resizeNotify(p, relOrigin, relSize, absOrigin, absSize); +} + +#define X(x) \ +METHOD(XonoticScrollPanel, x, bool(XonoticScrollPanel this, vector pos)) \ +{ \ + SUPER(XonoticScrollPanel).x(this, pos); \ + XonoticTab p = this.currentPanel; \ + this.setFocus(this, p); \ + \ + vector o = -eY * this.scrollPos; \ + vector s = eX * (1 - this.controlWidth) + eY * this.itemHeight; \ + return p.x(p, globalToBox(pos, o, s)); \ +} +X(mouseMove) +X(mousePress) +X(mouseDrag) +X(mouseRelease) +#undef X + +#define X(x) \ +METHOD(XonoticScrollPanel, x, bool(XonoticScrollPanel this, int key, int ascii, bool shift)) \ +{ \ + XonoticTab p = this.currentPanel; \ + return p.x(p, key, ascii, shift) || SUPER(XonoticScrollPanel).x(this, key, ascii, shift); \ +} +X(keyDown) +X(keyUp) +#undef X diff --git a/qcsrc/menu/xonotic/scrollpanel.qh b/qcsrc/menu/xonotic/scrollpanel.qh new file mode 100644 index 000000000..f675e863d --- /dev/null +++ b/qcsrc/menu/xonotic/scrollpanel.qh @@ -0,0 +1,24 @@ +#pragma once + +#include "listbox.qh" +#include "tab.qh" +CLASS(XonoticScrollPanel, XonoticListBox) + /** container for single child panel */ + ATTRIB(XonoticScrollPanel, currentPanel, entity, NEW(XonoticTab)); + ATTRIB(XonoticScrollPanel, nItems, int, 1); + ATTRIB(XonoticScrollPanel, selectionDoesntMatter, bool, true); + ATTRIB(XonoticScrollPanel, itemHeight, float, 1); + /** number of rows to show at once */ + ATTRIB(XonoticScrollPanel, viewportHeight, float, 12); + ATTRIB(XonoticScrollPanel, alphaBG, float, 0); + + METHOD(XonoticScrollPanel, getItemAtPos, float(XonoticScrollPanel this, float pos)) { return 0; } + METHOD(XonoticScrollPanel, getItemHeight, float(XonoticScrollPanel this, int i)) { return this.itemHeight; } + METHOD(XonoticScrollPanel, getItemStart, float(XonoticScrollPanel this, int i)) { return 0; } + METHOD(XonoticScrollPanel, getTotalHeight, float(XonoticScrollPanel this)) { return this.itemHeight; } + METHOD(XonoticScrollPanel, setFocus, void(XonoticScrollPanel this, entity other)) { Container_setFocus(this, other); } + METHOD(XonoticScrollPanel, setSelected, void(XonoticScrollPanel this, int i)) { } + + METHOD(XonoticScrollPanel, drawListBoxItem, void(XonoticScrollPanel this, int i, vector absSize, bool isSelected, bool isFocused)); + METHOD(XonoticScrollPanel, resizeNotify, void(XonoticScrollPanel this, vector relOrigin, vector relSize, vector absOrigin, vector absSize)); +ENDCLASS(XonoticScrollPanel) -- 2.39.2