#1321 Area Search: one window, with the parcel's and region's land impact split by owner #1331

Manually merged
sky_line merged 0 commits from TheSlowly/Slipstream:area-search-parcel-li into main 2026-10-31 22:11:22 +00:00
Collaborator

Fixes #1321: Area Search spread its filters over several tabs, and there was no easy way to see what is using a parcel's land impact.

  • One window: pick where to look (This parcel, Region, Nearby with a radius, or a parcel from About Land). One search box covers every field, with optional regex. Filters are Any / Only / Hide, with the rarer ones under More filters.
  • Land impact breakdown: a header shows used of allowed LI, counted as About Land does, and a bar splits it by owner. Click an owner to list only their objects. On a parcel the list sorts by LI.
  • Region: adds up every parcel's server count, looked up a few at a time and read-only. Nearby: what has loaded in range, by owner.
  • About Land > Objects > List objects opens Area Search on that parcel.
  • The old Area Search settings are replaced by one setting, SlipstreamAreaSearchState.

Tested in-world. Unit tests cover the filters, the parcel summary and the region parcel map.

Fixes #1321: Area Search spread its filters over several tabs, and there was no easy way to see what is using a parcel's land impact. - **One window:** pick where to look (This parcel, Region, Nearby with a radius, or a parcel from About Land). One search box covers every field, with optional regex. Filters are Any / Only / Hide, with the rarer ones under More filters. - **Land impact breakdown:** a header shows used of allowed LI, counted as About Land does, and a bar splits it by owner. Click an owner to list only their objects. On a parcel the list sorts by LI. - **Region:** adds up every parcel's server count, looked up a few at a time and read-only. **Nearby:** what has loaded in range, by owner. - **About Land > Objects > List objects** opens Area Search on that parcel. - The old Area Search settings are replaced by one setting, `SlipstreamAreaSearchState`. Tested in-world. Unit tests cover the filters, the parcel summary and the region parcel map.
Area Search's filters were two lists of checkboxes ("Only list objects that are" and
"Exclude objects that are") and its search was six separate fields. The new window has one
Any / Only / Hide control per property and one search box with a field picker. This is the
part with no viewer state, so it is unit-tested on its own.

SLAreaSearchFilters holds a state per property (temporary, attachment, physical, phantom,
locked, scripted, shared media, for sale, copy / modify / transfer, reflection probe, child
prim), the sale price range (applied when For sale is Only) and the click-action filter in
the existing combo's encoding. It saves to and reads from LLSD; missing or out-of-range
values read back as the defaults (attachments and child prims hidden, the rest Any).

SLAreaSearchText is the search box: a case-insensitive substring, or a regex that must match
a whole field (case-insensitive), in one field or any of them. An invalid regex is refused
and the previous query stays in force.

tests/slareasearchfilter_test.cpp: 9 tests, all passing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Area Search's parcel view needs three things the viewer has no helper for. First, whether
an object stands on a given parcel, which may be a parcel other than the agent's. Second,
the parcel's capacity as About Land computes it. Third, the used land impact split by owner.
This is the part with no viewer state.

SLParcelCells reads a ParcelProperties bitmap (one bit per 4 m cell, least significant bit
first, as writeAgentParcelFromBitmap reads it) and answers whether a region position is on
the parcel; a bitmap of the wrong size is refused. sl_parcel_capacity is About Land's
arithmetic: max objects times the object bonus, capped at the region's object limit.
sl_land_impact truncates the server's linkset cost, as the Build floater and Object Weights
do (#781). sl_summarize_parcel sums land impact per owner (the group for group-owned
objects), largest first with ties in id order. It keeps the top five and sums the rest into
"others". What the server counts beyond the viewer's sum is reported as not loaded yet,
never negative.

tests/slparcelsummary_test.cpp: 7 tests, all passing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Area Search's parcel view needs a parcel's name, area, used and maximum object counts and
its cell bitmap. That covers the agent's parcel, and a parcel picked in About Land after the
land selection has moved on. Selecting land would give those numbers, but it moves the
in-world highlight and About Land with it, and the selection does not last: any in-world
click deselects land, and editing an object re-selects that object's parcel.

requestParcelContents sends ParcelPropertiesRequestByID with its own sequence id and is
routed the way requestParcelIdentity already is: never touching the selection, the
highlight or the agent parcel; same 64-pending limit, 10 s timeout, session and sender
checks; the callback gets undefined on any failure. The registration and timeout now live in
beginParcelLookup, which both lookups share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Area Search had five sub-tabs. Its filters were split into "Only list" and "Exclude"
checkboxes with an Apply button. The way to focus on one parcel was a checkbox on the third
tab, and nothing listed until Search was pressed. It is now one window: a filter panel on
the left and the list on the right.

Left panel:
- Look in: This parcel (the one you stand on, following you), Region, or Nearby (within N m,
  neighbouring regions included). Replaces "Current Parcel only", "Distance between" and
  "Neighboring Regions".
- Search: one box with a field picker (All fields, Name, Description, Owner, Group, Creator,
  Last owner) and a regular-expression option. It applies as you type, after a short pause.
  An invalid regex keeps the previous search and greys the text, with the reason in its
  tooltip, instead of a popup per key.
- Show: one Any / Only / Hide control each for temporary, attachments, physical, phantom,
  locked, scripted (new), shared media and for sale.
- More filters: copy / modify / transfer, reflection probes, child prims, the sale price
  range (when For sale is Only) and the click action.

Filters apply as they change, by re-listing from the cached object details. Only child
prims and attachments decide what is fetched; newly eligible objects are fetched as they are
seen. On a parcel the list sorts by land impact, largest first; elsewhere by distance. Land
impact shows as the Build floater shows it.

The Options tab's column checkboxes moved to a right-click on the list header. The Advanced
tab's double-click extras (touch, buy, sit; the tab was hidden by default) moved to a gear
menu by the Refresh button. The window's state is one LLSD setting,
SlipstreamAreaSearchState, saved as it changes. The 25 old Area Search filter settings and
FSAreaSearchAdvanced are gone. The default columns are LI, Name, Owner, Distance and Prims.

"Filter My Objects" searches the owner field for your name until the owner filter in the
next commit replaces it.

Test-Plan: Open Area Search (Build menu or its toolbar button). It is one window with no
  tabs, listing the objects of the parcel you stand on, biggest LI first.
  Walk onto another parcel: the list follows. Pick Region, then Nearby, and change the
  metres: the list follows each, sorted by distance.
  Type in the search box: the list narrows shortly after you stop typing. Try each field
  in the picker. Tick Regular expression and type "(": the text greys out, its tooltip
  says why, and the previous search still applies.
  Set each Show row to Only and to Hide: the list follows at once. Open More filters and
  try the permissions, Child prims, the price range with For sale on Only, and a click
  action.
  Right-click the list header: tick and untick columns. In the gear menu, tick "Also
  touch on double-click", then double-click a scripted object: the camera goes to it and
  it is touched.
  Relog: the scope, filters, More filters and gear choices are as you left them.
  Busy region: toggle filters and type quickly; the viewer does not hitch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On This parcel, Area Search now opens with what the parcel uses. Above the list is the
parcel's name and area, "312 of 351 LI", and a bar split by owner. When the owner's parcels
share a region-wide pool that differs from the parcel's own numbers, the pool is shown too.
The header numbers are About Land's: the server's count, and max objects times the object
bonus, capped at the region's limit. The window gets them with the read-only parcel lookup,
so the land selection, the parcel highlight and About Land are untouched. It asks on open, on
Refresh, when you walk onto another parcel, and at most every 5 s while objects appear on or
vanish from the parcel, so the header follows rezzing and returns.

The bar is drawn from the cached objects on the parcel: roots, not attachments, not
temporary, whatever the search and filters show. The five largest owners get a colour each;
the rest share "others". What the server counts beyond the objects loaded so far shows as
"not loaded yet", then the free part. Clicking an owner's segment or legend entry lists only
that owner's objects (group-owned objects under the group); clicking again lists everyone's.
The owner filter works in every scope. "Filter My Objects" now sets it to you instead of
typing your name into a search field, and "Show all owners" clears it. Owner names in the
bar and the filter line are hidden under RLV @shownames like the list's.

Also defines FSAreaSearch_Cost_Label ("L$ [COST]"): the Price column looked it up but it
was never defined, so for-sale objects showed a missing-string marker.

Test-Plan: Stand on a parcel with objects from more than one owner and open Area Search.
  Numbers match: once loading settles, "N of M LI" matches About Land > Objects
  ("Objects used on parcel" / "Parcel supports"). The bar's owner totals add up to N,
  less anything still marked "not loaded yet".
  Rez an object on the parcel, then delete it: within about 5 s the header follows.
  Click an owner in the bar or its legend: only their objects are listed, and a line
  above the list names them. Click again, or press "Show all owners": everyone's again.
  Right-click a row > Filter My Objects: only your objects, in any scope.
  Pick Region or Nearby: the summary goes away; This parcel brings it back.
  RLV names: under @shownames, owner names in the bar and the filter line are hidden.
  Lookup fails: on a very slow connection the header shows "..." and fills in later.
  For-sale objects show "L$ <price>" in the Price column.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
About Land > Objects only lists owners, with a total each, and only for the parcel's owner
and managers. A List objects button now opens Area Search on the parcel About Land shows,
biggest land impact first, for anyone. That works for any parcel in the region you are in.
The button is disabled, with a tooltip saying why, for a parcel in another region, because
the viewer only has the current region's objects.

In Area Search the parcel appears as a fourth "Look in" choice, labelled with the parcel's
name ("Parcel from About Land", greyed out, until one is picked). Its cells come from the
parcel's own properties bitmap through the read-only lookup, so the pin outlives About Land
closing, in-world clicks and the Edit action, all of which change the land selection. It
stays put while you walk, and the summary above the list describes it. Picking another
scope drops it. Leaving the region drops it too and goes back to This parcel. A pin is not
remembered across sessions.

Test-Plan: Open About Land on a neighbouring parcel in your region (click its land, then
  About Land) and press List objects on the Objects tab. Area Search opens with that
  parcel's name under Look in, lists only that parcel's objects biggest LI first, and the
  header matches About Land's "Objects used on parcel" and "Parcel supports".
  Close About Land, click around in-world and use Edit on a listed object: the list stays
  on that parcel. Walk around: it does not follow you.
  Pick This parcel: the list follows you again and the pinned choice greys out.
  Select a parcel across a region border in About Land: List objects is disabled, and its
  tooltip says only parcels in your region can be listed.
  Teleport while pinned: afterwards Area Search is back on This parcel.
  As a visitor on someone else's land, List objects works even though About Land's owner
  list says you cannot list objects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Column menu: LLScrollListCtrl only passes right-clicks on rows to its callback, so the
  header menu never opened and the hidden columns could not be brought back. The list panel
  now handles a right-click on the column headers itself.
- Name lookups: every re-list subscribed again for names still pending, and only the last
  connection was kept. Now that typing and every filter change re-list, a name could
  arrive several times, and after the window closed it could call back into the freed
  window. There is now one subscription per name, kept until it arrives, and all of them
  are disconnected on close.
- Used land impact: the lookup reported the wire's TotalPrims. About Land shows owner +
  group + other + selected (LLParcel::getPrimCount()), and the header now reports that sum,
  so the two always match.
- The search box also commits when it loses focus. After typing, the first click into the
  list re-listed it, which reset the scroll and could put a different row under a
  double-click. A commit that changes nothing is now ignored.
- RLV @shownames now also re-hides the owner line and the bar's legend at once. Group names
  stay visible everywhere under @shownames, the list's Owner column included, as in the
  Group column.
- Parcel lookups are matched by region as well as local id, so a late answer from the
  region just left is ignored. The pin stores a region id instead of a region pointer. A
  lookup that fails is retried up to five times, 5 s apart.
- Smaller: the summary follows cost replies on a pinned parcel too; a radius change no
  longer resets the column sort; owner names in the bar are shortened on a UTF-8 character
  boundary; the bar marks itself for redraw when it changes; the column menu is destroyed
  with the window.

Test-Plan: Right-click the list's column headers: the column menu opens; untick and tick
  columns.
  Type a search, scroll the list down, then double-click a row: the camera goes to that
  row's object, and the list does not jump back to the top.
  With an owner picked in the bar, turn on RLV @shownames: the owner line and the bar's
  names are hidden at once; group names stay.
  On a parcel with objects being selected or sat on, the header's used count matches
  About Land's "Objects used on parcel".
  Open Area Search in a busy region, type a few searches, and close it before the names
  finish loading: no crash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The parcel header and the owner bar only showed for This parcel. On a region that is a single
parcel, switching to Region lost a breakdown of the very same land.

No message reports a region's used land impact, so Region adds it up from its parcels, as About
Land counts each one. Area Search looks every parcel up once through one of its 4 m cells. It
asks one cell per group the parcel overlay's property lines enclose, four lookups at a time; a
parcel in pieces is asked once, since its bitmap covers them all. A parcel is asked again by id
when the root objects seen on it change, but only once the region's objects have settled, so
objects still streaming in after a teleport cause no extra lookups. The region's limit is its
object capacity. The lookups only run while Region is picked and are kept for the session in
that region; Refresh starts them over.

Nearby has no limit to compare with: its bar splits what has loaded in range by owner, without
"free".

Parcel and region names in the header follow RLV @showloc. Roots now count toward the parcel
re-request check as soon as they are seen, not once their properties arrive, which also cuts the
parcel lookups while a parcel loads.

Test-Plan: Open Area Search and pick Region. The header shows the region name, then
  "N parcels" and "X of Y LI" once every parcel has been looked up (a few seconds on mainland).
  The bar splits it by owner; "not loaded yet" shrinks as costs arrive, and "free" is the rest.
  On a region that is one parcel, This parcel and Region show the same used count.
  In Region, rez an object and wait a few seconds: the used count goes up by its land impact.
  Pick Nearby: "Within 64 m" and the land impact loaded in range, split by owner, no "free".
  In Region and in Nearby, click an owner in the bar: the list shows only their objects.
  With RLV @showloc, the parcel and region names show as hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The legend was laid out left to right and dropped whatever did not fit. With a few long owner
names, the entries at the end went first: "not loaded yet" and "free", which are what tell you
whether the numbers are complete and how much room is left.

Those totals are now placed first. The owner names share what width is left: every name is cut
to the same length, from 24 characters down to 6, and if that is still too wide the smallest
owners are left out of the legend. Their bar segments stay, and clicking them still picks the
owner.

Test-Plan: On a parcel where several owners have long names, and objects still loading or LI
  free, make Area Search narrow: the legend keeps "not loaded yet" and "free" at the end, and the
  owner names shorten with "..." instead.
  Make it narrower still: the smallest owners leave the legend; clicking their bar segment still
  filters the list to them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each listed row whose object had gone or left the scope was removed on its own: a search for
its index, then an erase from the middle of the list, both linear. Walking onto another parcel
can drop thousands of rows at once, so that was quadratic and could stall the viewer for a
moment on busy land.

The rows to drop are now collected first and removed in a single pass, through a new
LLScrollListCtrl::deleteItemsIf() that deletes every item a predicate picks.

Test-Plan: On a busy parcel with thousands of objects, open Area Search on This parcel and walk
  onto another parcel: the list changes over without a hitch, and the rows are the new parcel's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Holding one of the radius spinner's arrows commits on every step, and each commit cleared and
rebuilt the list, which in a busy region is a lot of work many times a second. A radius change
now waits for the value to stop changing for a moment (the same pause as typing a search), then
re-lists once.

Test-Plan: In Nearby, hold the radius spinner's up arrow from 64 to about 200 m in a busy region:
  the viewer stays smooth while the number climbs, and the list updates once you let go.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The window remembers its size in floater_rect_area_search. The old tabbed layout was 610 px
wide, so anyone who had resized it opened the new one-window layout at its 640 px minimum
instead of the 820 px it is designed for, with the list and the header cramped.

The new layout keeps its size under a setting of its own, floater_rect_area_search_v2, so it
starts at its default size once and is remembered from there. The saved position is a separate
setting and stays.

Test-Plan: With a viewer that used the old Area Search and resized it, open Area Search: it
  opens at the new default size (820 x 460) where it was before. Resize it, close it and open
  it again: the new size stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sky_line manually merged commit aa7609acca into main 2026-10-31 22:11:22 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sky_line/Slipstream!1331
No description provided.