Skip to content

Qtfred special points#7614

Closed
MjnMixael wants to merge 21 commits into
scp-fs2open:masterfrom
MjnMixael:qtfred-special-points
Closed

Qtfred special points#7614
MjnMixael wants to merge 21 commits into
scp-fs2open:masterfrom
MjnMixael:qtfred-special-points

Conversation

@MjnMixael

Copy link
Copy Markdown
Contributor

Coordinate Points (Special Points)

Adds a new mission object type: coordinate points - named, positioned markers backed by a real Objects[] slot (OBJ_COORDINATE_POINT). Like waypoints, they hold a position but no physics; unlike waypoints, they carry display and gameplay metadata (color, 2D shape, size, escort-list priority, TvT team restriction) and can be rendered and targeted in-mission.

What's included

  • Object type + rendering - flat 2D shapes drawn at the point's location; optional in-mission visibility (editor-only by default).
  • QtFRED editor - full Coordinate Point dialog (shape as NGon/Star/Custom radios + tabled-shape dropdown, color, size, angle, escort priority, team, layer, visibility), scene browser / layer manager / mission stats integration, and help docs.
  • Shapes table - new coordinate_points.tbl (#Coordinate Shapes) defining custom tabled shapes, extensible by mods via *-cps.tbm (additive; duplicate and reserved names rejected).
  • SEXPs - two new operators (point-targeted, toggle-point-visibility) plus a new OPF_COORDINATE_POINT arg type. Existing position/distance/geometry operators now accept coordinate points: get-object-x/y/z, set-object-position, distance / distance-to-center / distance-bbox (and the *-to-subsystem variants), is-in-box, set-object-facing-object, angle-fvec-target, and the camera facing-object / host / target operators.
  • Lua - l_CoordinatePoint type (name, group, position, escort priority, visibility, team, escort add/remove) and a mission.CoordinatePoints sublibrary (index by number or name, # length); OSWPT handles resolve to coordinate points.
  • Multiplayer - points participate in net-signature serialization; set-object-position and toggle-point-visibility sync to clients; per-point TvT team filtering on render.

Shapes table (coordinate_points.tbl)

Each entry needs a $Name:, a $Vertices: list (flat x y float pairs at unit radius, point-up, wound CCW), and a $Triangles: list (flat CCW vertex indices, three per triangle). The names NGon and Star are reserved for the procedural primitives. Example (the shipped Cross):

#Coordinate Shapes

$Name: Cross
$Vertices: (
    -0.33  1.00     0.33  1.00     0.33  0.33     1.00  0.33
     1.00 -0.33     0.33 -0.33     0.33 -1.00    -0.33 -1.00
    -0.33 -0.33    -1.00 -0.33    -1.00  0.33    -0.33  0.33
)
$Triangles: (
    ; vertical bar
     0  7  6      0  6  1
    ; horizontal bar
    10  9  4     10  4  3
)

#End

Notes

  • Backwards compatible: no changes to existing mission behavior; the new #Coordinate Points block and coordinate_points.tbl are optional. +Shape: accepts legacy aliases (Triangle/Diamond/Pentagon → NGon presets).
  • create-/delete-coordinate-point SEXPs are intentionally deferred (runtime naming + multiplayer object-creation complexity); the Lua API and #Coordinate Points cover authored points.

MjnMixael added 21 commits July 8, 2026 10:31
Add CODE_OF_CONDUCT, CONTRIBUTING, GOVERNANCE, COMMUNITY_QUEUE, issue/discussion templates, and Readme updates for the OFP fork.
- Add scoped `contents: write` to the create_release and *_zip jobs so a
  release_* tag can create the GitHub release and publish assets (OFP repo's
  default workflow token is read-only, which would 403 these steps).
- Any tag with a '-' suffix (RCs, date-stamped nightlies like 26_1_0-20260713)
  publishes as a prerelease; a clean release_MM_mm_bb is a full release.
Add an FSO_BUILD_FORK_NAME define (empty on stock builds, "OFP" on OFP
builds), driven by cmake/version.cmake through project.h.in. When set:

- gameversion::get_version_string() reports "FreeSpace 2 Open (OFP) v<ver>",
  which brands the main hall, the player-menu copyright line, and Lua's
  ba.getVersionString() (single chokepoint for all three).
- the startup log header (fs2_open.log / fred2_open.log / standalone /
  qtFRED, all via outwnd) gains a "This is an OFP build." line.

The numeric version is unchanged, so mod required_fso_version checks and
Nebula semver are unaffected. Lua scripts can detect an OFP build with
  ba.getVersionString():find("(OFP)", 1, true)
which needs no new API and therefore never errors on stock SCP builds
(accessing an unregistered ba member raises a LuaError).
- nebula.py: target the OFP engine (id/title/mod_flag = OFP; tile/banner by checksum,
  which works without Nebula's URLS_FOR allowlist); add a per-release `private` flag.
- main.py: drop the Hard-Light forum post and indiegames FTP/mirror config while keeping
  the Nebula submit; read NEBULA_PRIVATE (default private); derive the release version from
  the git tag (OFP has no generated version_override.cmake); pick Nebula stability
  (stable/rc/nightly) from the version shape; stub the dead nightly branch.
- Upload build archives into Nebula's own storage by default (no URLS_FOR allowlist needed);
  set NEBULA_USE_URLS=true to instead register GitHub Release URLs once the account is
  allowlisted. installer.py gains an after_hash hook so the upload reuses the one download.
- file_list.py: map the Windows "ARM64" package name to the WinARM64 Nebula key.
- post-build-release.yaml: drop INDIEGAMES_*/HLP_* env, keep NEBULA_*, add the
  NEBULA_PRIVATE and NEBULA_USE_URLS repo variables, and rename the job.

Releases upload to Nebula privately until NEBULA_PRIVATE=false.
* allow models for intel entries

* address feedback
sexp.cpp keeps its own private OSWPT_TYPE_* macro aliases; add the
coordinate-point one so the new case labels compile.
The shape row now uses three radio buttons (NGon, Star, Custom) with the
tabled-shape dropdown to their right, disabled unless Custom is selected.
Custom is disabled when no tabled shapes are loaded. This distinguishes
generated primitives from tabled shapes in the UI.
The Sides and Points spinboxes used a minimum of 2 (one below the real
NGON/STAR minimum of 3) as the mixed-selection blank sentinel, which let a
single selection spin down to a meaningless value. Drop the floor to the
sentinel only while the value is actually mixed; otherwise the minimum is
the true lower bound.
Sides/Points now toggle specialValueText with the mixed state so the blank
sentinel renders (and a real value at the floor still shows its number).
Angle had no mixed handling at all; give it a -361 blank sentinel like Size
and Escort Priority, and guard setAngle against committing it. Inner Radius,
Size, Escort Priority, and the color spinboxes already blanked correctly.
Every value spinbox now works identically: a fixed below-range sentinel
renders blank via specialValueText, the model setter clamps/rejects it, and
the valueChanged handler calls updateUi() to snap a single selection back to
the real value. This adds the missing updateUi() snap-back to Sides, Points,
Inner Radius, Angle, and the color spinboxes, reverts the Sides/Points
dynamic-minimum hack, and pushes each box's own minimum() for the mixed
value so specialValueText reliably blanks (fixes Inner Radius showing
-0.010 at 3 decimals).
Their specialValueText came from the .ui as a single space, which gets
trimmed to empty on load and silently disables the blank. Set it in the
constructor like the other sentinel spinboxes so mixed selections render
blank instead of showing the sentinel number.
@MjnMixael
MjnMixael requested review from asarium and z64555 as code owners July 17, 2026 19:01
@MjnMixael MjnMixael closed this Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant