From: Mario Date: Sun, 18 Oct 2020 21:55:54 +0000 (+1000) Subject: Merge branch 'master' into TimePath/guide X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=ae85011bcd8894f7b79f34bf626cf366f21d391e;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into TimePath/guide --- ae85011bcd8894f7b79f34bf626cf366f21d391e diff --cc qcsrc/common/vehicles/vehicle.qh index b358c1d91a,8da44a459a..51c849dcf2 --- a/qcsrc/common/vehicles/vehicle.qh +++ b/qcsrc/common/vehicles/vehicle.qh @@@ -1,59 -1,62 +1,66 @@@ - #ifndef VEHICLE_H - #define VEHICLE_H + #pragma once CLASS(Vehicle, Object) - ATTRIB(Vehicle, vehicleid, int, 0) + ATTRIB(Vehicle, vehicleid, int, 0); /** hud icon */ - ATTRIB(Vehicle, m_icon, string, string_null) + ATTRIB(Vehicle, m_icon, string); /** short name */ - ATTRIB(Vehicle, netname, string, "") + ATTRIB(Vehicle, netname, string, ""); /** human readable name */ - ATTRIB(Vehicle, vehicle_name, string, "Vehicle") + ATTRIB(Vehicle, vehicle_name, string, "Vehicle"); /** full name of model */ - ATTRIB(Vehicle, model, string, "") + ATTRIB(Vehicle, model, string, ""); /** currently a copy of the model */ - ATTRIB(Vehicle, mdl, string, "") + ATTRIB(Vehicle, mdl, string, ""); /** full name of tur_head model */ - ATTRIB(Vehicle, head_model, string, "") + ATTRIB(Vehicle, head_model, string, ""); /** cockpit model */ - ATTRIB(Vehicle, hud_model, string, "") + ATTRIB(Vehicle, hud_model, string, ""); /** tur_head model tag */ - ATTRIB(Vehicle, tag_head, string, string_null) + ATTRIB(Vehicle, tag_head, string); /** hud model tag */ - ATTRIB(Vehicle, tag_hud, string, string_null) + ATTRIB(Vehicle, tag_hud, string); /** cockpit model tag */ - ATTRIB(Vehicle, tag_view, string, string_null) + ATTRIB(Vehicle, tag_view, string); /** player physics mod */ - ATTRIB(Vehicle, PlayerPhysplug, int(), func_null) + ATTRIB(Vehicle, PlayerPhysplug, bool(entity,float)); /** */ - ATTRIB(Vehicle, spawnflags, int, 0) + ATTRIB(Vehicle, spawnflags, int, 0); /** vehicle hitbox size */ - ATTRIB(Vehicle, mins, vector, '-0 -0 -0') + ATTRIB(Vehicle, m_mins, vector, '-0 -0 -0'); /** vehicle hitbox size */ - ATTRIB(Vehicle, maxs, vector, '0 0 0') + ATTRIB(Vehicle, m_maxs, vector, '0 0 0'); + /** vehicle 3rd person view offset */ + ATTRIB(Vehicle, view_ofs, vector, '0 0 0'); + /** vehicle 3rd person view distance */ + ATTRIB(Vehicle, height, float, 0); + METHOD(Vehicle, display, void(entity this, void(string name, string icon) returns)) { + returns(this.vehicle_name, this.m_icon ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon) : string_null); + } + /** (BOTH) setup vehicle data */ - METHOD(Vehicle, vr_setup, void(Vehicle)) { } + METHOD(Vehicle, vr_setup, void(Vehicle this, entity instance)) { } /** (SERVER) logic to run every frame */ - METHOD(Vehicle, vr_think, void(Vehicle)) { } + METHOD(Vehicle, vr_think, void(Vehicle this, entity instance)) { } /** (SERVER) called when vehicle dies */ - METHOD(Vehicle, vr_death, void(Vehicle)) { } + METHOD(Vehicle, vr_death, void(Vehicle this, entity instance)) { } /** (BOTH) precaches models/sounds used by this vehicle */ - METHOD(Vehicle, vr_precache, void(Vehicle)) { } + METHOD(Vehicle, vr_precache, void(Vehicle this)) { } /** (SERVER) called when a player enters this vehicle */ - METHOD(Vehicle, vr_enter, void(Vehicle)) { } + METHOD(Vehicle, vr_enter, void(Vehicle this, entity instance)) { } + /** (SERVER) called when a player enters this vehicle while occupied */ + METHOD(Vehicle, vr_gunner_enter, void(Vehicle this, entity instance, entity actor)) { } /** (SERVER) called when the vehicle re-spawns */ - METHOD(Vehicle, vr_spawn, void(Vehicle)) { } + METHOD(Vehicle, vr_spawn, void(Vehicle this, entity instance)) { } /** (SERVER) called when a vehicle hits something */ - METHOD(Vehicle, vr_impact, void(Vehicle)) { } + METHOD(Vehicle, vr_impact, void(Vehicle this, entity instance)) { } + /** (SERVER) called when a vehicle's colors are being reset, so modules can be updated */ + METHOD(Vehicle, vr_setcolors, void(Vehicle this, entity instance)) { } /** (CLIENT) logic to run every frame */ - METHOD(Vehicle, vr_hud, void(Vehicle)) { } + METHOD(Vehicle, vr_hud, void(Vehicle this)) { } /** (CLIENT) logic to run every frame */ - METHOD(Vehicle, vr_crosshair, void(Vehicle)) { } + METHOD(Vehicle, vr_crosshair, void(Vehicle thisveh, entity player)) { } ENDCLASS(Vehicle) // vehicle spawn flags (need them here for common registrations) diff --cc qcsrc/menu/classes.inc index beb3b65688,8b13789179..0000000000 deleted file mode 100644,100644 --- a/qcsrc/menu/classes.inc +++ /dev/null @@@ -1,141 -1,1 +1,0 @@@ - #include "anim/animation.qc" - #include "anim/animhost.qc" - #include "anim/easing.qc" - #include "anim/keyframe.qc" - - #include "item.qc" - #include "item/borderimage.qc" - #include "item/button.qc" - #include "item/checkbox.qc" - #include "item/container.qc" - #include "item/dialog.qc" - #include "item/image.qc" - #include "item/inputbox.qc" - #include "item/inputcontainer.qc" - #include "item/label.qc" - #include "item/listbox.qc" - #include "item/modalcontroller.qc" - #include "item/nexposee.qc" - #include "item/radiobutton.qc" - #include "item/slider.qc" - #include "item/tab.qc" - #include "item/textslider.qc" -- - #include "xonotic/bigbutton.qc" - #include "xonotic/bigcommandbutton.qc" - #include "xonotic/button.qc" - #include "xonotic/campaign.qc" - #include "xonotic/charmap.qc" - #include "xonotic/checkbox.qc" - #include "xonotic/checkbox_slider_invalid.qc" - #include "xonotic/checkbox_string.qc" - #include "xonotic/colorbutton.qc" - #include "xonotic/colorpicker.qc" - #include "xonotic/colorpicker_string.qc" - #include "xonotic/commandbutton.qc" - #include "xonotic/credits.qc" - #include "xonotic/crosshairpicker.qc" - #include "xonotic/crosshairpreview.qc" - #include "xonotic/cvarlist.qc" - #include "xonotic/datasource.qc" - #include "xonotic/demolist.qc" - #include "xonotic/dialog.qc" - #include "xonotic/dialog_credits.qc" - #include "xonotic/dialog_firstrun.qc" - #include "xonotic/dialog_hudpanel_ammo.qc" - #include "xonotic/dialog_hudpanel_centerprint.qc" - #include "xonotic/dialog_hudpanel_chat.qc" - #include "xonotic/dialog_hudpanel_engineinfo.qc" - #include "xonotic/dialog_hudpanel_healtharmor.qc" - #include "xonotic/dialog_hudpanel_infomessages.qc" - #include "xonotic/dialog_hudpanel_itemstime.qc" - #include "xonotic/dialog_hudpanel_modicons.qc" - #include "xonotic/dialog_hudpanel_notification.qc" - #include "xonotic/dialog_hudpanel_physics.qc" - #include "xonotic/dialog_hudpanel_powerups.qc" - #include "xonotic/dialog_hudpanel_pressedkeys.qc" - #include "xonotic/dialog_hudpanel_quickmenu.qc" - #include "xonotic/dialog_hudpanel_racetimer.qc" - #include "xonotic/dialog_hudpanel_radar.qc" - #include "xonotic/dialog_hudpanel_score.qc" - #include "xonotic/dialog_hudpanel_timer.qc" - #include "xonotic/dialog_hudpanel_vote.qc" - #include "xonotic/dialog_hudpanel_weapons.qc" - #include "xonotic/dialog_hudsetup_exit.qc" - #include "xonotic/dialog_monstertools.qc" - #include "xonotic/dialog_multiplayer.qc" - #include "xonotic/dialog_multiplayer_create.qc" - #include "xonotic/dialog_multiplayer_create_mapinfo.qc" - #include "xonotic/dialog_multiplayer_create_mutators.qc" - #include "xonotic/dialog_multiplayer_join.qc" - #include "xonotic/dialog_multiplayer_join_serverinfo.qc" - #include "xonotic/dialog_multiplayer_media.qc" - #include "xonotic/dialog_multiplayer_media_demo.qc" - #include "xonotic/dialog_multiplayer_media_demo_startconfirm.qc" - #include "xonotic/dialog_multiplayer_media_demo_timeconfirm.qc" - #include "xonotic/dialog_multiplayer_media_musicplayer.qc" - #include "xonotic/dialog_multiplayer_media_screenshot.qc" - #include "xonotic/dialog_multiplayer_media_screenshot_viewer.qc" - #include "xonotic/dialog_multiplayer_profile.qc" - #include "xonotic/dialog_quit.qc" - #include "xonotic/dialog_sandboxtools.qc" - #include "xonotic/dialog_settings.qc" - #include "xonotic/dialog_settings_audio.qc" - #include "xonotic/dialog_settings_effects.qc" - #include "xonotic/dialog_settings_game.qc" - #include "xonotic/dialog_settings_game_crosshair.qc" - #include "xonotic/dialog_settings_game_hudconfirm.qc" - #include "xonotic/dialog_settings_game_hud.qc" - #include "xonotic/dialog_settings_game_messages.qc" - #include "xonotic/dialog_settings_game_model.qc" - #include "xonotic/dialog_settings_game_view.qc" - #include "xonotic/dialog_settings_game_weapons.qc" - #include "xonotic/dialog_settings_input.qc" - #include "xonotic/dialog_settings_input_userbind.qc" - #include "xonotic/dialog_settings_misc.qc" - #include "xonotic/dialog_settings_misc_cvars.qc" - #include "xonotic/dialog_settings_misc_reset.qc" - #include "xonotic/dialog_settings_user.qc" - #include "xonotic/dialog_settings_user_languagewarning.qc" - #include "xonotic/dialog_settings_video.qc" - #include "xonotic/dialog_singleplayer.qc" - #include "xonotic/dialog_singleplayer_winner.qc" - #include "xonotic/dialog_teamselect.qc" - #include "xonotic/gametypelist.qc" - #include "xonotic/guide/description.qc" - #include "xonotic/guide/entries.qc" - #include "xonotic/guide/tab.qc" - #include "xonotic/guide/topics.qc" - #include "xonotic/hudskinlist.qc" - #include "xonotic/image.qc" - #include "xonotic/inputbox.qc" - #include "xonotic/keybinder.qc" - #include "xonotic/languagelist.qc" - #include "xonotic/listbox.qc" - #include "xonotic/mainwindow.qc" - #include "xonotic/maplist.qc" - #include "xonotic/nexposee.qc" - #include "xonotic/picker.qc" - #include "xonotic/playerlist.qc" - #include "xonotic/playermodel.qc" - #include "xonotic/playlist.qc" - #include "xonotic/radiobutton.qc" - #include "xonotic/rootdialog.qc" - #include "xonotic/screenshotimage.qc" - #include "xonotic/screenshotlist.qc" - #include "xonotic/serverlist.qc" - #include "xonotic/skinlist.qc" - #include "xonotic/slider.qc" - #include "xonotic/slider_decibels.qc" - #include "xonotic/slider_particles.qc" - #include "xonotic/slider_picmip.qc" - #include "xonotic/slider_resolution.qc" - #include "xonotic/slider_sbfadetime.qc" - #include "xonotic/soundlist.qc" - #include "xonotic/statslist.qc" - #include "xonotic/tabcontroller.qc" - #include "xonotic/tab.qc" - #include "xonotic/textlabel.qc" - #include "xonotic/textslider.qc" - #include "xonotic/weaponarenacheckbox.qc" - #include "xonotic/weaponslist.qc" diff --cc qcsrc/menu/xonotic/guide/_mod.inc index 0000000000,0000000000..a38cbdaffe new file mode 100644 --- /dev/null +++ b/qcsrc/menu/xonotic/guide/_mod.inc @@@ -1,0 -1,0 +1,5 @@@ ++// generated file; do not modify ++#include ++#include ++#include ++#include diff --cc qcsrc/menu/xonotic/guide/_mod.qh index 0000000000,0000000000..c90a3f2ec3 new file mode 100644 --- /dev/null +++ b/qcsrc/menu/xonotic/guide/_mod.qh @@@ -1,0 -1,0 +1,5 @@@ ++// generated file; do not modify ++#include ++#include ++#include ++#include diff --cc qcsrc/menu/xonotic/guide/description.qc index 02f304ec5d,0000000000..35068c1e5b mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/description.qc +++ b/qcsrc/menu/xonotic/guide/description.qc @@@ -1,52 -1,0 +1,1 @@@ - #ifndef DIALOG_MEDIA_GUIDE_DESCRIPTION_H - #define DIALOG_MEDIA_GUIDE_DESCRIPTION_H - #include "../listbox.qc" - CLASS(XonoticGuideDescription, XonoticListBox) - ATTRIB(XonoticGuideDescription, rowsPerItem, float, 1) - ATTRIB(XonoticGuideDescription, selectionDoesntMatter, bool, true) - - METHOD(XonoticGuideDescription, setDescription, void(entity, string)); - ATTRIB(XonoticGuideDescription, description, string, string_null) - - METHOD(XonoticGuideDescription, resizeNotify, void(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize)) { - SUPER(XonoticGuideDescription).resizeNotify(this, relOrigin, relSize, absOrigin, absSize); - - this.realFontSize_y = this.fontSize / (absSize.y * this.itemHeight); - this.realFontSize_x = this.fontSize / (absSize.x * (1 - this.controlWidth)); - this.realUpperMargin = 0.5 * (1 - this.realFontSize.y); - this.setDescription(this, this.description); - } - - INIT(XonoticGuideDescription) { - this.configureXonoticListBox(this); - } - - ATTRIB(XonoticGuideDescription, descriptionWrapped, string, string_null) - void XonoticGuideDescription_setDescription(entity this, string desc) - { - string current = this.description; - if (current && current != desc) strunzone(current); - this.description = strzone(desc); - - string currentWrapped = this.descriptionWrapped; - if (currentWrapped) strunzone(currentWrapped); - string wrapped = ""; - for (int i = 0, n = tokenizebyseparator(desc, "\n"); i < n; ++i) { - string line = ""; - for (getWrappedLine_remaining = argv(i); getWrappedLine_remaining; ) { - string s = getWrappedLine(1, this.realFontSize, draw_TextWidth_WithColors); - line = sprintf("%s\n%s", line, s); - } - wrapped = strcat(wrapped, line); - } - this.descriptionWrapped = strzone(wrapped); - - this.nItems = tokenizebyseparator(wrapped, "\n"); - } - - METHOD(XonoticGuideDescription, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused)) { - tokenizebyseparator(this.descriptionWrapped, "\n"); - draw_Text(this.realUpperMargin * eY, argv(i), this.realFontSize, '1 1 1', 1, 0); - } - ENDCLASS(XonoticGuideDescription) - #endif ++#include "description.qh" diff --cc qcsrc/menu/xonotic/guide/description.qh index 0000000000,0000000000..1e8b6ea7ca new file mode 100644 --- /dev/null +++ b/qcsrc/menu/xonotic/guide/description.qh @@@ -1,0 -1,0 +1,51 @@@ ++#pragma once ++ ++#include ++CLASS(XonoticGuideDescription, XonoticListBox) ++ ATTRIB(XonoticGuideDescription, rowsPerItem, float, 1); ++ ATTRIB(XonoticGuideDescription, selectionDoesntMatter, bool, true); ++ ++ METHOD(XonoticGuideDescription, setDescription, void(entity, string)); ++ ATTRIB(XonoticGuideDescription, description, string, string_null); ++ ++ METHOD(XonoticGuideDescription, resizeNotify, void(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize)) { ++ SUPER(XonoticGuideDescription).resizeNotify(this, relOrigin, relSize, absOrigin, absSize); ++ ++ this.realFontSize_y = this.fontSize / (absSize.y * this.itemHeight); ++ this.realFontSize_x = this.fontSize / (absSize.x * (1 - this.controlWidth)); ++ this.realUpperMargin = 0.5 * (1 - this.realFontSize.y); ++ this.setDescription(this, this.description); ++ } ++ ++ INIT(XonoticGuideDescription) { ++ this.configureXonoticListBox(this); ++ } ++ ++ ATTRIB(XonoticGuideDescription, descriptionWrapped, string, string_null); ++ void XonoticGuideDescription_setDescription(entity this, string desc) ++ { ++ string current = this.description; ++ if (current && current != desc) strunzone(current); ++ this.description = strzone(desc); ++ ++ string currentWrapped = this.descriptionWrapped; ++ if (currentWrapped) strunzone(currentWrapped); ++ string wrapped = ""; ++ for (int i = 0, n = tokenizebyseparator(desc, "\n"); i < n; ++i) { ++ string line = ""; ++ for (getWrappedLine_remaining = argv(i); getWrappedLine_remaining; ) { ++ string s = getWrappedLine(1, this.realFontSize, draw_TextWidth_WithColors); ++ line = sprintf("%s\n%s", line, s); ++ } ++ wrapped = strcat(wrapped, line); ++ } ++ this.descriptionWrapped = strzone(wrapped); ++ ++ this.nItems = tokenizebyseparator(wrapped, "\n"); ++ } ++ ++ METHOD(XonoticGuideDescription, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused)) { ++ tokenizebyseparator(this.descriptionWrapped, "\n"); ++ draw_Text(this.realUpperMargin * eY, argv(i), this.realFontSize, '1 1 1', 1, 0); ++ } ++ENDCLASS(XonoticGuideDescription) diff --cc qcsrc/menu/xonotic/guide/entries.qc index a65e31f087,0000000000..7084e3b6d8 mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/entries.qc +++ b/qcsrc/menu/xonotic/guide/entries.qc @@@ -1,127 -1,0 +1,91 @@@ - #ifndef DIALOG_MEDIA_GUIDE_ENTRIES_H - #define DIALOG_MEDIA_GUIDE_ENTRIES_H - #include "../datasource.qc" - #include "../listbox.qc" - CLASS(XonoticEntryList, XonoticListBox) - ATTRIB(XonoticEntryList, alphaBG, float, 0) - ATTRIB(XonoticEntryList, itemAbsSize, vector, '0 0 0') - ATTRIB(XonoticEntryList, origin, vector, '0 0 0') - ATTRIB(XonoticEntryList, realFontSize, vector, '0 0 0') - ATTRIB(XonoticEntryList, realUpperMargin1, float, 0) - ATTRIB(XonoticEntryList, realUpperMargin2, float, 0) - ATTRIB(XonoticEntryList, rowsPerItem, float, 4) - ATTRIB(XonoticEntryList, stringFilterBox, entity, NULL) - ATTRIB(XonoticEntryList, stringFilter, string, string_null) - ATTRIB(XonoticEntryList, typeToSearchString, string, string_null) - ATTRIB(XonoticEntryList, typeToSearchTime, float, 0) - - METHOD(XonoticEntryList, drawListBoxItem, void(entity, int, vector, bool, bool)); - METHOD(XonoticEntryList, keyDown, float(entity, float, float, float)); - METHOD(XonoticEntryList, refilter, void(entity)); - METHOD(XonoticEntryList, resizeNotify, void(entity, vector, vector, vector, vector)); - METHOD(XonoticEntryList, setSelected, void(entity, int)); - - ATTRIB(XonoticEntryList, source, DataSource, NULL) - - CONSTRUCTOR(XonoticEntryList, DataSource _source) { - CONSTRUCT(XonoticEntryList); - this.source = _source; - this.configureXonoticListBox(this); - this.refilter(this); - } - - ENDCLASS(XonoticEntryList) - #endif - - #ifdef IMPLEMENTATION ++#include "entries.qh" + +string XonoticEntryList_cb_name, XonoticEntryList_cb_icon; +void XonoticEntryList_cb(string _name, string _icon) { + XonoticEntryList_cb_name = _name; + XonoticEntryList_cb_icon = _icon; +} + +void XonoticEntryList_drawListBoxItem(entity this, int i, vector absSize, bool isSelected, bool isFocused) +{ + if (!this.source) return; + if (!this.source.getEntry(this.source, i, XonoticEntryList_cb)) return; + string name = XonoticEntryList_cb_name; + string icon = XonoticEntryList_cb_icon; + if (isSelected) { + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); + } else if (isFocused) { + this.focusedItemAlpha = getFadedAlpha(this.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED); + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, this.focusedItemAlpha); + } + vector sz = draw_PictureSize(icon); + if (!sz) sz = '1 1 0'; + float szr = sz.x / sz.y; + if (strstrofs(icon, "map", 0) >= 0) szr = 4 / 3; + float asr = this.itemAbsSize.x / this.itemAbsSize.y; + sz.y = 1; sz.x = szr / asr; + draw_Picture('0 0 0', icon, sz, '1 1 1', SKINALPHA_LISTBOX_SELECTED); + string s = draw_TextShortenToWidth(strdecolorize(name), 1 - sz.x - 2 * this.realFontSize.x, 0, this.realFontSize); + draw_Text(this.realUpperMargin1 * eY + (sz.x + 0.5 * this.realFontSize.x) * eX, s, this.realFontSize, '1 1 1', SKINALPHA_TEXT, 0); +} + +METHOD(XonoticEntryList, keyDown, float(entity this, float scan, float ascii, float shift)) +{ + if (this.nItems <= 0) { + return SUPER(XonoticEntryList).keyDown(this, scan, ascii, shift); + } else if ((ascii >= 32 || scan == K_BACKSPACE) && this.source.indexOf) { + string save; + if (scan == K_BACKSPACE) { + save = substring(this.typeToSearchString, 0, strlen(this.typeToSearchString) - 1); + } else { + string ch = chr(ascii); + save = (time > this.typeToSearchTime) ? ch : strcat(this.typeToSearchString, ch); + } + if (this.typeToSearchString) strunzone(this.typeToSearchString); + this.typeToSearchString = strzone(save); + this.typeToSearchTime = time + 0.5; + if (strlen(this.typeToSearchString)) { + int idx = this.source.indexOf(this.source, this.typeToSearchString); + if (idx >= 0) this.setSelected(this, idx); + } + } else if (shift & S_CTRL && scan == 'f') { + this.parent.setFocus(this.parent, this.stringFilterBox); + } else if (shift & S_CTRL && scan == 'u') { + this.stringFilterBox.setText(this.stringFilterBox, ""); + if (this.stringFilter) strunzone(this.stringFilter); + this.stringFilter = string_null; + this.refilter(this); + } + return SUPER(XonoticEntryList).keyDown(this, scan, ascii, shift); +} + +void XonoticEntryList_refilter(entity this) +{ + if (!this.source) { + this.nItems = 0; + return; + } + this.nItems = this.source.reload(this.source, this.stringFilter); + for (int i = 0, n = this.nItems; i < n; ++i) { + if (this.source.getEntry(this.source, i, XonoticEntryList_cb)) { + draw_PreloadPicture(XonoticEntryList_cb_icon); + } + } +} + +void XonoticEntryList_resizeNotify(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize) +{ + this.itemAbsSize = '0 0 0'; + SUPER(XonoticEntryList).resizeNotify(this, relOrigin, relSize, absOrigin, absSize); + + this.realFontSize_y = this.fontSize / (this.itemAbsSize_y = (absSize.y * this.itemHeight)); + this.realFontSize_x = this.fontSize / (this.itemAbsSize_x = (absSize.x * (1 - this.controlWidth))); + this.realUpperMargin1 = 0.5 * (1 - 2.5 * this.realFontSize.y); + this.realUpperMargin2 = this.realUpperMargin1 + 1.5 * this.realFontSize.y; +} + +void XonoticEntryList_setSelected(entity this, int i) +{ + SUPER(XonoticEntryList).setSelected(this, i); + this.onChange(this, this.onChangeEntity); +} - #endif diff --cc qcsrc/menu/xonotic/guide/entries.qh index 0000000000,0000000000..ea1d599dc9 new file mode 100644 --- /dev/null +++ b/qcsrc/menu/xonotic/guide/entries.qh @@@ -1,0 -1,0 +1,33 @@@ ++#pragma once ++ ++#include ++#include ++CLASS(XonoticEntryList, XonoticListBox) ++ ATTRIB(XonoticEntryList, alphaBG, float, 0); ++ ATTRIB(XonoticEntryList, itemAbsSize, vector, '0 0 0'); ++ ATTRIB(XonoticEntryList, origin, vector, '0 0 0'); ++ ATTRIB(XonoticEntryList, realFontSize, vector, '0 0 0'); ++ ATTRIB(XonoticEntryList, realUpperMargin1, float, 0); ++ ATTRIB(XonoticEntryList, realUpperMargin2, float, 0); ++ ATTRIB(XonoticEntryList, rowsPerItem, float, 4); ++ ATTRIB(XonoticEntryList, stringFilterBox, entity, NULL); ++ ATTRIB(XonoticEntryList, stringFilter, string, string_null); ++ ATTRIB(XonoticEntryList, typeToSearchString, string, string_null); ++ ATTRIB(XonoticEntryList, typeToSearchTime, float, 0); ++ ++ METHOD(XonoticEntryList, drawListBoxItem, void(entity, int, vector, bool, bool)); ++ METHOD(XonoticEntryList, keyDown, float(entity, float, float, float)); ++ METHOD(XonoticEntryList, refilter, void(entity)); ++ METHOD(XonoticEntryList, resizeNotify, void(entity, vector, vector, vector, vector)); ++ METHOD(XonoticEntryList, setSelected, void(entity, int)); ++ ++ ATTRIB(XonoticEntryList, source, DataSource, NULL); ++ ++ CONSTRUCTOR(XonoticEntryList, DataSource _source) { ++ CONSTRUCT(XonoticEntryList); ++ this.source = _source; ++ this.configureXonoticListBox(this); ++ this.refilter(this); ++ } ++ ++ENDCLASS(XonoticEntryList) diff --cc qcsrc/menu/xonotic/guide/pages.qh index 92731738b9,0000000000..caaebd83f5 mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/pages.qh +++ b/qcsrc/menu/xonotic/guide/pages.qh @@@ -1,29 -1,0 +1,26 @@@ - #ifndef GUIDE_PAGES_H - #define GUIDE_PAGES_H ++#pragma once + +CLASS(GuidePage, Object); + ATTRIB(GuidePage, m_id, int, 0); + ATTRIB(GuidePage, m_title, string, ""); + ATTRIB(GuidePage, m_description, string, ""); + METHOD(GuidePage, describe, string(GuidePage this)) { + return this.m_description; + } + METHOD(GuidePage, display, void(GuidePage this, void(string name, string icon) returns)) { + returns(this.m_title, "nopreview_map"); + } + CONSTRUCTOR(GuidePage, string _title) { + CONSTRUCT(GuidePage); + this.m_title = _title; + } +ENDCLASS(GuidePage) + +REGISTRY(GuidePages, 16) +#define REGISTER_GUIDE_PAGE(id, title) \ + REGISTER(GuidePages, GUIDE_PAGE, id, m_id, NEW(GuidePage, title)) +REGISTER_REGISTRY(GuidePages) + +REGISTER_GUIDE_PAGE(0, _("Intro")) { this.m_description = _( +"Welcome to xonotic" +);} - - #endif diff --cc qcsrc/menu/xonotic/guide/tab.qc index 472132d985,0000000000..8b14a82fa6 mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/tab.qc +++ b/qcsrc/menu/xonotic/guide/tab.qc @@@ -1,230 -1,0 +1,66 @@@ - #ifndef DIALOG_MEDIA_GUIDE_H - #define DIALOG_MEDIA_GUIDE_H - #include "../datasource.qc" - - #define TOPICS(X) \ - X(NEW(FreetextSource), _("Guide"), "gametype_tdm") \ - X(NEW(GametypeSource), _("Gametypes"), "gametype_dm") \ - X(NEW(WeaponSource), _("Weapons"), "gametype_ka") \ - X(NEW(ItemSource), _("Items"), "gametype_kh") \ - X(NEW(BuffSource), _("Buffs"), "gametype_dom") \ - X(NEW(NadeSource), _("Nades"), "gametype_ft") \ - X(NEW(MonsterSource), _("Monsters"), "gametype_lms") \ - X(NEW(VehicleSource), _("Vehicles"), "gametype_rc") \ - X(NEW(TurretSource), _("Turrets"), "gametype_as") \ - X(NEW(MutatorSource), _("Mutators"), "gametype_nb") \ - X(NEW(MapSource), _("Maps"), "gametype_ctf") \ - if (cvar("developer")) X(NEW(DebugSource), _("Debug"), "gametype_ons") \ - /**/ - CLASS(TopicSource, DataSource) - METHOD(TopicSource, getEntry, entity(TopicSource this, int i, void(string, string) returns)) { - int idx = 0; - #define TOPIC(src, name, icon) if (idx++ == i) { if (returns) returns(name, icon); return DataSource_true; } - TOPICS(TOPIC); - #undef TOPIC - if (returns) returns("undefined", "undefined"); - return DataSource_false; - } - METHOD(TopicSource, reload, int(TopicSource this, string filter)) { - int n = 0; - #define TOPIC(src, name, icon) n++; - TOPICS(TOPIC); - #undef TOPIC - return n; - } - ENDCLASS(TopicSource) - - CLASS(DebugSource, DataSource) - .entity nextdebug; - entity find_debug() { - entity head = NULL, tail = NULL; - for (entity it = NULL; (it = nextent(it)); ) { - if (!it.instanceOfObject) continue; - if (it.instanceOfItem) continue; - if (it.instanceOfAnimHost) continue; - if (it.instanceOfDataSource) continue; - if (it.classname == "Object") continue; - if (it.classname == "vtbl") continue; - if (!tail) { - tail = head = it; - } else { - tail.nextdebug = it; - tail = it; - } - } - return head; - } - string DebugSource_activeFilter = ""; - METHOD(DebugSource, getEntry, entity(DebugSource this, int i, void(string, string) returns)) { - int idx = 0; - entity e; - for (e = find_debug(); e; e = e.nextdebug) { - if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue; - if (idx++ == i) break; - } - if (returns) e.display(e, returns); - return e; - } - METHOD(DebugSource, reload, int(DebugSource this, string filter)) { - DebugSource_activeFilter = filter; - int idx = 0; - entity e; - for (e = find_debug(); e; e = e.nextdebug) { - if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue; - idx++; - } - return idx; - } - ENDCLASS(DebugSource) - - #define REGISTRY_SOURCE(id, arr) \ - CLASS(id, DataSource) \ - METHOD(id, getEntry, entity(id this, int i, void(string, string) returns)) { \ - entity e = _R_GET(_##arr, i); \ - if (returns) e.display(e, returns); \ - return e; \ - } \ - METHOD(id, reload, int(id this, string filter)) { return arr##_COUNT; } \ - ENDCLASS(id) - - #include "pages.qh" - REGISTRY_SOURCE(FreetextSource, GuidePages) - - #include "../../../common/mapinfo.qh" - REGISTRY_SOURCE(GametypeSource, Gametypes) - - #include "../../../common/items/all.qh" - REGISTRY_SOURCE(ItemSource, Items) - - #include "../../../common/mutators/mutator/buffs/all.qh" - REGISTRY_SOURCE(BuffSource, Buffs) - - #include "../../../common/mutators/mutator/nades/nades.qh" - REGISTRY_SOURCE(NadeSource, Nades) - - #include "../../../common/weapons/all.qh" - REGISTRY_SOURCE(WeaponSource, Weapons) - - #include "../../../common/monsters/all.qh" - REGISTRY_SOURCE(MonsterSource, Monsters) - - #include "../../../common/vehicles/all.qh" - REGISTRY_SOURCE(VehicleSource, Vehicles) - - #include "../../../common/turrets/all.qh" - REGISTRY_SOURCE(TurretSource, Turrets) - - #include "../../../common/mutators/base.qh" - REGISTRY_SOURCE(MutatorSource, Mutators) - - CLASS(MapSource, DataSource) - METHOD(MapSource, getEntry, entity(MapSource this, int i, void(string, string) returns)) { - if (!MapInfo_Get_ByID(i)) return DataSource_false; - string path = strcat("/maps/", MapInfo_Map_bspname); - string img = draw_PictureSize(path) ? path : "nopreview_map"; - if (returns) returns(MapInfo_Map_titlestring, img); - MapInfo_ClearTemps(); - return DataSource_true; - } - METHOD(MapSource, indexOf, int(MapSource this, string s)) { - MapInfo_FindName(s); - return MapInfo_FindName_firstResult; - } - METHOD(MapSource, reload, int(MapSource this, string s)) { - MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 0); - if (s) MapInfo_FilterString(s); - return MapInfo_count; - } - METHOD(MapSource, destroy, void(MapSource this)) { MapInfo_Shutdown(); } - ENDCLASS(MapSource) - - #include "topics.qc" - #include "entries.qc" - #include "description.qc" - #include "../tab.qc" - CLASS(XonoticGuideTab, XonoticTab) - ATTRIB(XonoticGuideTab, rows, float, 21) - ATTRIB(XonoticGuideTab, columns, float, 6) - ATTRIB(XonoticGuideTab, intendedWidth, float, 1) - METHOD(XonoticGuideTab, fill, void(entity)); - METHOD(XonoticGuideTab, topicChangeNotify, void(entity, entity)); - METHOD(XonoticGuideTab, entryChangeNotify, void(entity, entity)); - - ATTRIB(XonoticGuideTab, topicList, entity, NEW(XonoticTopicList, NEW(TopicSource))) - ATTRIB(XonoticGuideTab, entryList, entity, NEW(XonoticEntryList, NULL)) - ATTRIB(XonoticGuideTab, descriptionPane, entity, NEW(XonoticGuideDescription)) - - INIT(XonoticGuideTab) { - this.configureDialog(this); - } - ENDCLASS(XonoticGuideTab) - #endif - - #ifdef IMPLEMENTATION ++#include "tab.qh" + +void XonoticGuideTab_fill(entity this) +{ + entity topics = this.topicList; + topics.onChange = XonoticGuideTab_topicChangeNotify; + topics.onChangeEntity = this; + entity entries = this.entryList; + entries.onChange = XonoticGuideTab_entryChangeNotify; + entries.onChangeEntity = this; + entity filter = entries.stringFilterBox = makeXonoticInputBox(false, string_null); + filter.keyDown = MapList_StringFilterBox_keyDown; + filter.onChange = MapList_StringFilterBox_Change; + filter.onChangeEntity = entries; + entries.controlledTextbox = filter; + entity description = this.descriptionPane; + + int + col = 0, width = 1.5; + this.gotoRC(this, 0, col); + this.TD(this, 1, width, makeXonoticHeaderLabel(_("Topic"))); + this.TR(this); + this.TD(this, this.rows - 1, width, topics); + + col += width, width = 2; + this.gotoRC(this, 0, col); this.setFirstColumn(this, this.currentColumn); + this.TD(this, 1, width, makeXonoticHeaderLabel(_("Entry"))); + this.TR(this); + this.TD(this, this.rows - 1 - 1, width, entries); + this.gotoRC(this, this.rows - 1, col); + this.TD(this, 1, 0.3, makeXonoticTextLabel(0, _("Filter:"))); + this.TD(this, 1, width - 0.3, filter); + + col += width, width = 2.5; + this.gotoRC(this, 0, col); this.setFirstColumn(this, this.currentColumn); + this.TD(this, 1, width, makeXonoticHeaderLabel(_("Description"))); + this.TR(this); + this.TD(this, this.rows - 1, width, description); + + this.topicChangeNotify(topics, this); +} + +void XonoticGuideTab_topicChangeNotify(entity, entity this) +{ + entity topics = this.topicList; + entity entries = this.entryList; + int i = topics.selectedItem; + int idx = 0; + entity found = NULL; + #define TOPIC(src, name, icon) if (idx++ == i) { static entity e; if (!e) e = src; found = e; break; } + do { TOPICS(TOPIC); } while (0); + #undef TOPIC + entries.source = found; + entries.refilter(entries); + entries.setSelected(entries, 0); +} + +void XonoticGuideTab_entryChangeNotify(entity, entity this) +{ + entity desc = this.descriptionPane; + entity entries = this.entryList; + entity e = entries.source.getEntry(entries.source, entries.selectedItem, func_null); + string s = e.describe(e); + if (cvar("developer")) { s = sprintf("entity %i\n%s", e, s); } + desc.setDescription(desc, s); +} - - #endif diff --cc qcsrc/menu/xonotic/guide/tab.qh index 0000000000,0000000000..ad791856c2 new file mode 100644 --- /dev/null +++ b/qcsrc/menu/xonotic/guide/tab.qh @@@ -1,0 -1,0 +1,160 @@@ ++#pragma once ++ ++#include ++ ++#define TOPICS(X) \ ++ X(NEW(FreetextSource), _("Guide"), "gametype_tdm") \ ++ X(NEW(GametypeSource), _("Gametypes"), "gametype_dm") \ ++ X(NEW(WeaponSource), _("Weapons"), "gametype_ka") \ ++ X(NEW(ItemSource), _("Items"), "gametype_kh") \ ++ X(NEW(BuffSource), _("Buffs"), "gametype_dom") \ ++ X(NEW(NadeSource), _("Nades"), "gametype_ft") \ ++ X(NEW(MonsterSource), _("Monsters"), "gametype_lms") \ ++ X(NEW(VehicleSource), _("Vehicles"), "gametype_rc") \ ++ X(NEW(TurretSource), _("Turrets"), "gametype_as") \ ++ X(NEW(MutatorSource), _("Mutators"), "gametype_nb") \ ++ X(NEW(MapSource), _("Maps"), "gametype_ctf") \ ++ if (cvar("developer")) X(NEW(DebugSource), _("Debug"), "gametype_ons") \ ++ /**/ ++CLASS(TopicSource, DataSource) ++ METHOD(TopicSource, getEntry, entity(TopicSource this, int i, void(string, string) returns)) { ++ int idx = 0; ++ #define TOPIC(src, name, icon) if (idx++ == i) { if (returns) returns(name, icon); return DataSource_true; } ++ TOPICS(TOPIC); ++ #undef TOPIC ++ if (returns) returns("undefined", "undefined"); ++ return DataSource_false; ++ } ++ METHOD(TopicSource, reload, int(TopicSource this, string filter)) { ++ int n = 0; ++ #define TOPIC(src, name, icon) n++; ++ TOPICS(TOPIC); ++ #undef TOPIC ++ return n; ++ } ++ENDCLASS(TopicSource) ++ ++CLASS(DebugSource, DataSource) ++ .entity nextdebug; ++ entity find_debug() { ++ entity head = NULL, tail = NULL; ++ for (entity it = NULL; (it = nextent(it)); ) { ++ if (!it.instanceOfObject) continue; ++ if (it.instanceOfGameItem) continue; ++ if (it.instanceOfAnimHost) continue; ++ if (it.instanceOfDataSource) continue; ++ if (it.classname == "Object") continue; ++ if (it.classname == "vtbl") continue; ++ if (!tail) { ++ tail = head = it; ++ } else { ++ tail.nextdebug = it; ++ tail = it; ++ } ++ } ++ return head; ++ } ++ string DebugSource_activeFilter = ""; ++ METHOD(DebugSource, getEntry, entity(DebugSource this, int i, void(string, string) returns)) { ++ int idx = 0; ++ entity e; ++ for (e = find_debug(); e; e = e.nextdebug) { ++ if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue; ++ if (idx++ == i) break; ++ } ++ if (returns) e.display(e, returns); ++ return e; ++ } ++ METHOD(DebugSource, reload, int(DebugSource this, string filter)) { ++ DebugSource_activeFilter = filter; ++ int idx = 0; ++ entity e; ++ for (e = find_debug(); e; e = e.nextdebug) { ++ if (strstrofs(sprintf("entity %i", e), DebugSource_activeFilter, 0) < 0) continue; ++ idx++; ++ } ++ return idx; ++ } ++ENDCLASS(DebugSource) ++ ++#define REGISTRY_SOURCE(id, arr) \ ++CLASS(id, DataSource) \ ++ METHOD(id, getEntry, entity(id this, int i, void(string, string) returns)) { \ ++ entity e = _R_GET(_##arr, i); \ ++ if (returns) e.display(e, returns); \ ++ return e; \ ++ } \ ++ METHOD(id, reload, int(id this, string filter)) { return arr##_COUNT; } \ ++ENDCLASS(id) ++ ++#include "pages.qh" ++REGISTRY_SOURCE(FreetextSource, GuidePages) ++ ++#include ++REGISTRY_SOURCE(GametypeSource, Gametypes) ++ ++#include ++REGISTRY_SOURCE(ItemSource, Items) ++ ++#include ++REGISTRY_SOURCE(BuffSource, Buffs) ++ ++#include ++REGISTRY_SOURCE(NadeSource, Nades) ++ ++#include ++REGISTRY_SOURCE(WeaponSource, Weapons) ++ ++#include ++REGISTRY_SOURCE(MonsterSource, Monsters) ++ ++#include ++REGISTRY_SOURCE(VehicleSource, Vehicles) ++ ++#include ++REGISTRY_SOURCE(TurretSource, Turrets) ++ ++#include ++REGISTRY_SOURCE(MutatorSource, Mutators) ++ ++CLASS(MapSource, DataSource) ++ METHOD(MapSource, getEntry, entity(MapSource this, int i, void(string, string) returns)) { ++ if (!MapInfo_Get_ByID(i)) return DataSource_false; ++ string path = strcat("/maps/", MapInfo_Map_bspname); ++ string img = draw_PictureSize(path) ? path : "nopreview_map"; ++ if (returns) returns(MapInfo_Map_titlestring, img); ++ MapInfo_ClearTemps(); ++ return DataSource_true; ++ } ++ METHOD(MapSource, indexOf, int(MapSource this, string s)) { ++ MapInfo_FindName(s); ++ return MapInfo_FindName_firstResult; ++ } ++ METHOD(MapSource, reload, int(MapSource this, string s)) { ++ _MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 0); ++ if (s) MapInfo_FilterString(s); ++ return MapInfo_count; ++ } ++ METHOD(MapSource, destroy, void(MapSource this)) { MapInfo_Shutdown(); } ++ENDCLASS(MapSource) ++ ++#include "topics.qh" ++#include "entries.qh" ++#include "description.qh" ++#include ++CLASS(XonoticGuideTab, XonoticTab) ++ ATTRIB(XonoticGuideTab, rows, float, 21); ++ ATTRIB(XonoticGuideTab, columns, float, 6); ++ ATTRIB(XonoticGuideTab, intendedWidth, float, 1); ++ METHOD(XonoticGuideTab, fill, void(entity)); ++ METHOD(XonoticGuideTab, topicChangeNotify, void(entity, entity)); ++ METHOD(XonoticGuideTab, entryChangeNotify, void(entity, entity)); ++ ++ ATTRIB(XonoticGuideTab, topicList, entity, NEW(XonoticTopicList, NEW(TopicSource))); ++ ATTRIB(XonoticGuideTab, entryList, entity, NEW(XonoticEntryList, NULL)); ++ ATTRIB(XonoticGuideTab, descriptionPane, entity, NEW(XonoticGuideDescription)); ++ ++ INIT(XonoticGuideTab) { ++ this.configureDialog(this); ++ } ++ENDCLASS(XonoticGuideTab) diff --cc qcsrc/menu/xonotic/guide/topics.qc index f1b6408cbd,0000000000..f47fb72eb6 mode 100644,000000..100644 --- a/qcsrc/menu/xonotic/guide/topics.qc +++ b/qcsrc/menu/xonotic/guide/topics.qc @@@ -1,94 -1,0 +1,63 @@@ - #ifndef DIALOG_MEDIA_GUIDE_TOPICS_H - #define DIALOG_MEDIA_GUIDE_TOPICS_H - #include "../datasource.qc" - #include "../listbox.qc" - CLASS(XonoticTopicList, XonoticListBox) - ATTRIB(XonoticTopicList, columnIconOrigin, float, 0) - ATTRIB(XonoticTopicList, columnIconSize, float, 0) - ATTRIB(XonoticTopicList, columnNameOrigin, float, 0) - ATTRIB(XonoticTopicList, columnNameSize, float, 0) - ATTRIB(XonoticTopicList, realFontSize, vector, '0 0 0') - ATTRIB(XonoticTopicList, realUpperMargin, float, 0) - ATTRIB(XonoticTopicList, rowsPerItem, float, 3) - - METHOD(XonoticTopicList, clickListBoxItem, void(entity, float, vector)); - METHOD(XonoticTopicList, drawListBoxItem, void(entity, int, vector, bool, bool)); - METHOD(XonoticTopicList, keyDown, bool(entity, float, float, float)); - METHOD(XonoticTopicList, resizeNotify, void(entity, vector, vector, vector, vector)); - METHOD(XonoticTopicList, setSelected, void(entity, int)); - - ATTRIB(XonoticTopicList, source, DataSource, NULL) - - CONSTRUCTOR(XonoticTopicList, DataSource _source) { - CONSTRUCT(XonoticTopicList); - this.source = _source; - this.nItems = _source.reload(_source, ""); - this.configureXonoticListBox(this); - } - ENDCLASS(XonoticTopicList) - #endif - - #ifdef IMPLEMENTATION ++#include "topics.qh" + +void XonoticTopicList_clickListBoxItem(entity this, float i, vector where) +{ + m_play_click_sound(MENU_SOUND_SELECT); +} + +string XonoticTopicList_cb_name, XonoticTopicList_cb_icon; +void XonoticTopicList_cb(string _name, string _icon) { + XonoticTopicList_cb_name = _name; + XonoticTopicList_cb_icon = _icon; +} + +void XonoticTopicList_drawListBoxItem(entity this, int i, vector absSize, bool isSelected, bool isFocused) +{ + if (!this.source) return; + if (!this.source.getEntry(this.source, i, XonoticTopicList_cb)) return; + string icon = XonoticTopicList_cb_icon; + string name = XonoticTopicList_cb_name; + if (isSelected) { + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED); + } else if (isFocused) { + this.focusedItemAlpha = getFadedAlpha(this.focusedItemAlpha, SKINALPHA_LISTBOX_FOCUSED, SKINFADEALPHA_LISTBOX_FOCUSED); + draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_FOCUSED, this.focusedItemAlpha); + } + draw_Picture(this.columnIconOrigin * eX, icon, this.columnIconSize * eX + eY, '1 1 1', SKINALPHA_LISTBOX_SELECTED); + vector save_fontscale = draw_fontscale; + float f = draw_CondensedFontFactor(name, false, this.realFontSize, 1); + draw_fontscale.x *= f; + vector fs = this.realFontSize; + fs.x *= f; + draw_Text(this.realUpperMargin * eY + this.columnNameOrigin * eX, name, fs, '1 1 1', SKINALPHA_TEXT, 0); + draw_fontscale = save_fontscale; +} + +bool XonoticTopicList_keyDown(entity this, float scan, float ascii, float shift) +{ + if (scan == K_ENTER || scan == K_KP_ENTER) { + m_play_click_sound(MENU_SOUND_EXECUTE); + return true; + } + return SUPER(XonoticEntryList).keyDown(this, scan, ascii, shift); +} + +void XonoticTopicList_resizeNotify(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize) +{ + this.itemAbsSize = '0 0 0'; + SUPER(XonoticEntryList).resizeNotify(this, relOrigin, relSize, absOrigin, absSize); + + this.realFontSize_y = this.fontSize / (this.itemAbsSize_y = (absSize.y * this.itemHeight)); + this.realFontSize_x = this.fontSize / (this.itemAbsSize_x = (absSize.x * (1 - this.controlWidth))); + this.realUpperMargin = 0.5 * (1 - this.realFontSize.y); + this.columnIconOrigin = 0; + this.columnIconSize = this.itemAbsSize.y / this.itemAbsSize.x; + this.columnNameOrigin = this.columnIconOrigin + this.columnIconSize + (0.5 * this.realFontSize.x); + this.columnNameSize = 1 - this.columnIconSize - (1.5 * this.realFontSize.x); +} + +void XonoticTopicList_setSelected(entity this, int i) +{ + SUPER(XonoticEntryList).setSelected(this, i); + this.onChange(this, this.onChangeEntity); +} - #endif diff --cc qcsrc/menu/xonotic/guide/topics.qh index 0000000000,0000000000..cd84ce8dc7 new file mode 100644 --- /dev/null +++ b/qcsrc/menu/xonotic/guide/topics.qh @@@ -1,0 -1,0 +1,28 @@@ ++#pragma once ++ ++#include ++#include ++CLASS(XonoticTopicList, XonoticListBox) ++ ATTRIB(XonoticTopicList, columnIconOrigin, float, 0); ++ ATTRIB(XonoticTopicList, columnIconSize, float, 0); ++ ATTRIB(XonoticTopicList, columnNameOrigin, float, 0); ++ ATTRIB(XonoticTopicList, columnNameSize, float, 0); ++ ATTRIB(XonoticTopicList, realFontSize, vector, '0 0 0'); ++ ATTRIB(XonoticTopicList, realUpperMargin, float, 0); ++ ATTRIB(XonoticTopicList, rowsPerItem, float, 3); ++ ++ METHOD(XonoticTopicList, clickListBoxItem, void(entity, float, vector)); ++ METHOD(XonoticTopicList, drawListBoxItem, void(entity, int, vector, bool, bool)); ++ METHOD(XonoticTopicList, keyDown, bool(entity, float, float, float)); ++ METHOD(XonoticTopicList, resizeNotify, void(entity, vector, vector, vector, vector)); ++ METHOD(XonoticTopicList, setSelected, void(entity, int)); ++ ++ ATTRIB(XonoticTopicList, source, DataSource, NULL); ++ ++ CONSTRUCTOR(XonoticTopicList, DataSource _source) { ++ CONSTRUCT(XonoticTopicList); ++ this.source = _source; ++ this.nItems = _source.reload(_source, ""); ++ this.configureXonoticListBox(this); ++ } ++ENDCLASS(XonoticTopicList)