Skip to content

add the texture_map scripting handle and ship class replacement textures - #7765

Draft
Goober5000 wants to merge 2 commits into
scp-fs2open:masterfrom
Goober5000:enhancement/scripting_textures
Draft

Goober5000 wants to merge 2 commits into
scp-fs2open:masterfrom
Goober5000:enhancement/scripting_textures

Conversation

@Goober5000

@Goober5000 Goober5000 commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

The "material" scripting class in texturemap.cpp had never been used since it was written in 2007. This reworks it into a usable texture_map handle and hooks it into the API.

  • texture_map_h now stores model number, model instance id (-1 for a model-level handle), and material index, resolving pointers on every access. The Lua type is "texture_map".
  • All eight slots are exposed as virtvars (BaseMap, GlowMap, SpecularMap, NormalMap, HeightMap, MiscMap, ReflectanceMap, AmbientOcclusionMap), plus a numeric indexer and __len, read-only Index, IsTransparent and IsAmbient, and resetToOriginal() (model level) / resetToModel() (instance level). Reads and writes follow the same rules as the flat "textures" and "modelinstancetextures" handles, including reference counting.
  • New "texturemaps" and "modelinstancetexturemaps" array handles, returned by a TextureMaps virtvar on model, model_instance, ship, and prop. The instance-level virtvars accept assignment exactly like Textures does.
  • The filename lookup of the two flat indexers is now shared with the new handles via model_find_texture_slot() and model_instance_find_texture_slot(). Both now return the first material whose slot matches; the model-level indexer previously returned the last.
  • New read-only "texture_replacement" / "texture_replacements" handles expose a ship class's table-defined replacement textures by filename, via a ReplacementTextures virtvar on shipclass.
  • Fix Prop.Textures assignment, which copied the prop's own replacement textures instead of the source prop's, making it a no-op.

Depends on #7763 and #7766; in draft until those is merged.

@Goober5000 Goober5000 added enhancement A new feature or upgrade of an existing feature to add additional functionality. scripting A feature or issue related to LUA scripting labels Sep 5, 2026
@Goober5000
Goober5000 marked this pull request as draft September 6, 2026 05:34
Model instance replacement arrays and script-set model textures stored raw
bitmap handles without taking a load-count reference.  A script doing
ship.Textures["foo"] = gr.loadTexture("bar") therefore left the ship pointing
at a bitmap slot that was freed as soon as Lua collected the temporary
texture handle, and reused by whatever bitmap loaded next.

- Add bm_add_ref() / bm_release_ref() to bmpman so callers no longer need
  BMPMAN_INTERNAL to take a reference.  Both count on the first frame of an
  animation, so any frame may be passed and the release always hits the
  same entry as the add; neither counts render targets, since bm_release()
  will not release those anyway.  Use them in the scripting texture handle
  and the librocket rendering interface, which previously counted on
  whatever frame they were handed.
- Add bm_page_out() (bm_unload() with a new keep_reference option) for
  dropping a bitmap's data without giving up the caller's reference, and use
  it when paging out model textures and glow bank bitmaps.  The plain
  bm_unload() call used before consumed one reference without freeing when
  another holder remained, which was harmless while nothing ever released
  but would now leave the model with a dangling handle once the other
  holder did.
- Make model_texture_replace own its entries: the array is now private, is
  written only through adopt() / reference() / clear(), and releases every
  handle it holds when destroyed.  Convert every writer (mission and SEXP
  replacements, cockpit displays, scripting, qtFRED).  Render targets are
  the documented exception; the cockpit display code no longer pretends to
  release its target separately.
- Release the references that mission parsing and the texture replacement
  SEXPs take on replacement bitmaps when the parse objects are discarded;
  ships created from those objects hold their own.  Previously those
  references were never released.
- Add model_instance_load_replacement_textures() to load a table's
  replacement list into an instance by filename, and use it from
  ship_model_change, the lab, FRED, and qtFRED, which each had their own
  copy of that loop (and which each leaked the loader's references).
- Give texture_info an optional held reference so script-set model textures
  stay alive until reset, replaced, or paged out.  PageOut() now pages out
  or releases the texture the model loaded rather than whatever is
  currently drawn, which also stops the debris species swap from releasing
  a texture it does not own.
- Have the cached UI render instances carry their ship class's replacement
  textures, loaded once in model_set_up_techroom_instance(), and add
  model_get_cached_ui_render_instance_for_class() so that the tech room,
  ship and weapon select, loadout icons, and tech model rendering fetch the
  instance and its replacements with one call instead of each building a
  fresh array with bm_load() every frame, which leaked one load count per
  frame.  The instance cache is now keyed by ship class as well, since
  classes sharing a model may differ in replacement textures.  As a side
  effect, those screens and the briefing closeup now load table replacement
  textures the same way missions do, so "invisible" and animated
  replacements are honored in previews where they were previously ignored.
- Delete the briefing closeup's model instance when its icon is set up
  again or the briefing closes; previously every revisited icon leaked its
  instance, which now also pinned its replacement bitmaps.
- Skip a cockpit display whose texture is not on the cockpit model, with a
  warning; previously this indexed the replacement array with -1.
- Guard bmpman against static destructors that release bitmaps after an
  exit that skipped bm_close().
- Document the texture slot layout of the "textures" and
  "modelinstancetextures" Lua handles, fix the stale TM_NUM_TYPES comment,
  and correct the gr.loadTexture docs on texture lifetime.
- Glow bank bitmaps are now released when a model is unloaded, and support
  ships receive their class's replacement textures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Goober5000
Goober5000 force-pushed the enhancement/scripting_textures branch from 20d9047 to 8dcc78c Compare September 8, 2026 17:06
The "material" scripting class in texturemap.cpp had never been used since it
was written in 2007.  This reworks it into a usable texture_map handle and
hooks it into the API.

- texture_map_h now stores model number, model instance id (-1 for a
  model-level handle), and material index, resolving pointers on every access.
  The Lua type is "texture_map".
- All eight slots are exposed as virtvars (BaseMap, GlowMap, SpecularMap,
  NormalMap, HeightMap, MiscMap, ReflectanceMap, AmbientOcclusionMap), plus a
  numeric indexer and __len, read-only Index, IsTransparent and IsAmbient, and
  resetToOriginal() (model level) / resetToModel() (instance level).  Reads
  and writes follow the same rules as the flat "textures" and
  "modelinstancetextures" handles, including reference counting.
- New "texturemaps" and "modelinstancetexturemaps" array handles, returned by
  a TextureMaps virtvar on model, model_instance, ship, and prop.  The
  instance-level virtvars accept assignment exactly like Textures does.
- The filename lookup of the two flat indexers is now shared with the new
  handles via model_find_texture_slot() and
  model_instance_find_texture_slot().  Both now return the first material
  whose slot matches; the model-level indexer previously returned the last.
- New read-only "texture_replacement" / "texture_replacements" handles expose
  a ship class's table-defined replacement textures by filename, via a
  ReplacementTextures virtvar on shipclass.
- Fix Prop.Textures assignment, which copied the prop's own replacement
  textures instead of the source prop's, making it a no-op.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Goober5000
Goober5000 force-pushed the enhancement/scripting_textures branch from 8dcc78c to b211217 Compare September 8, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement A new feature or upgrade of an existing feature to add additional functionality. scripting A feature or issue related to LUA scripting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant