diff --git a/src/debug/DebugParts.cpp b/src/debug/DebugParts.cpp index 30748cd5b..7f0dea788 100644 --- a/src/debug/DebugParts.cpp +++ b/src/debug/DebugParts.cpp @@ -18,7 +18,7 @@ void DebugParts::Draw() Graphics * g = ui::Engine::Ref().g; int x = 0, y = 0, lpx = 0, lpy = 0; - String info = String::Build(sim->parts_lastActiveIndex, "/", NPART, " (", Format::Precision((float)sim->parts_lastActiveIndex/(NPART)*100.0f, 2), "%)"); + String info = String::Build(sim->parts.lastActiveIndex, "/", NPART, " (", Format::Precision((float)sim->parts.lastActiveIndex/(NPART)*100.0f, 2), "%)"); for (int i = 0; i < NPART; i++) { if (sim->parts[i].type) @@ -26,7 +26,7 @@ void DebugParts::Draw() else g->AddPixel({ x, y }, 0x000000_rgb .WithAlpha(180)); - if (i == sim->parts_lastActiveIndex) + if (i == sim->parts.lastActiveIndex) { lpx = x; lpy = y; diff --git a/src/graphics/Renderer.cpp b/src/graphics/Renderer.cpp index 6d42e7272..af5659b31 100644 --- a/src/graphics/Renderer.cpp +++ b/src/graphics/Renderer.cpp @@ -249,7 +249,7 @@ void Renderer::render_parts() int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0}; int drawing_budget = 1000000; //Serves as an upper bound for costly effects such as SPARK, FLARE and LFLARE - auto *parts = sim->parts; + auto &parts = sim->parts; if (gridSize)//draws the grid { for (ny=0; nyparts_lastActiveIndex; i++) { + for(i = 0; i<=sim->parts.lastActiveIndex; i++) { if (sim->parts[i].type && sim->parts[i].type >= 0 && sim->parts[i].type < PT_NUM) { t = sim->parts[i].type; @@ -801,7 +801,7 @@ void Renderer::render_parts() type = PT_PRTO; else if (type == PT_PRTO) type = PT_PRTI; - for (int z = 0; z <= sim->parts_lastActiveIndex; z++) + for (int z = 0; z <= sim->parts.lastActiveIndex; z++) { if (parts[z].type == type) { diff --git a/src/lua/LuaSimulation.cpp b/src/lua/LuaSimulation.cpp index c9dad3cbc..f3ed5480a 100644 --- a/src/lua/LuaSimulation.cpp +++ b/src/lua/LuaSimulation.cpp @@ -862,7 +862,7 @@ static int resetTemp(lua_State *L) auto &sd = SimulationData::CRef(); auto &elements = sd.elements; bool onlyConductors = luaL_optint(L, 1, 0); - for (int i = 0; i < sim->parts_lastActiveIndex; i++) + for (int i = 0; i < sim->parts.lastActiveIndex; i++) { if (sim->parts[i].type && (elements[sim->parts[i].type].HeatConduct || !onlyConductors)) { @@ -1286,7 +1286,7 @@ static int brush(lua_State *L) static int partsClosure(lua_State *L) { auto *lsi = GetLSI(); - for (int i = lua_tointeger(L, lua_upvalueindex(1)); i <= lsi->sim->parts_lastActiveIndex; ++i) + for (int i = lua_tointeger(L, lua_upvalueindex(1)); i <= lsi->sim->parts.lastActiveIndex; ++i) { if (lsi->sim->parts[i].type) { diff --git a/src/simulation/Air.cpp b/src/simulation/Air.cpp index 60f564559..376012bdf 100644 --- a/src/simulation/Air.cpp +++ b/src/simulation/Air.cpp @@ -418,7 +418,7 @@ void Air::ApproximateBlockAirMaps() { auto &sd = SimulationData::CRef(); auto &elements = sd.elements; - for (int i = 0; i <= sim.parts_lastActiveIndex; i++) + for (int i = 0; i <= sim.parts.lastActiveIndex; i++) { int type = sim.parts[i].type; if (!type) diff --git a/src/simulation/Editing.cpp b/src/simulation/Editing.cpp index ca8b995e6..241e97dbf 100644 --- a/src/simulation/Editing.cpp +++ b/src/simulation/Editing.cpp @@ -25,7 +25,7 @@ std::unique_ptr Simulation::CreateSnapshot() const snap->BlockAirH .insert (snap->BlockAirH .begin(), &air->bmap_blockairh[0][0], &air->bmap_blockairh[0][0] + NCELL); snap->FanVelocityX .insert (snap->FanVelocityX .begin(), &fvx [0][0] , &fvx [0][0] + NCELL); snap->FanVelocityY .insert (snap->FanVelocityY .begin(), &fvy [0][0] , &fvy [0][0] + NCELL); - snap->Particles .insert (snap->Particles .begin(), &parts [0] , &parts [0] + parts_lastActiveIndex + 1); + snap->Particles .insert (snap->Particles .begin(), &parts [0] , &parts [0] + parts.lastActiveIndex + 1); snap->PortalParticles.insert (snap->PortalParticles.begin(), &portalp[0][0][0], &portalp[0][0][0] + CHANNELS * 8 * 80); snap->WirelessData .insert (snap->WirelessData .begin(), &wireless[0][0] , &wireless[0][0] + CHANNELS * 2); snap->stickmen .insert (snap->stickmen .begin(), &fighters[0] , &fighters[0] + MAX_FIGHTERS); @@ -45,7 +45,7 @@ void Simulation::Restore(const Snapshot &snap) std::fill(elementCount, elementCount + PT_NUM, 0); elementRecount = true; force_stacking_check = true; - for (auto &part : parts) + for (auto &part : parts.data) { part.type = 0; } @@ -78,7 +78,7 @@ void Simulation::Restore(const Snapshot &snap) signs = snap.signs; frameCount = snap.FrameCount; rng.state(snap.RngState); - parts_lastActiveIndex = NPART - 1; + parts.lastActiveIndex = NPART - 1; RecalcFreeParticles(false); } @@ -90,7 +90,7 @@ void Simulation::clear_area(int area_x, int area_y, int area_w, int area_h) area_w = intersection.size.X; area_h = intersection.size.Y; float fx = area_x-.5f, fy = area_y-.5f; - for (int i = 0; i <= parts_lastActiveIndex; i++) + for (int i = 0; i <= parts.lastActiveIndex; i++) { if (parts[i].type) if (parts[i].x >= fx && parts[i].x <= fx+area_w+1 && parts[i].y >= fy && parts[i].y <= fy+area_h+1) diff --git a/src/simulation/ElementDefs.h b/src/simulation/ElementDefs.h index 3f16befde..f54edd41b 100644 --- a/src/simulation/ElementDefs.h +++ b/src/simulation/ElementDefs.h @@ -39,7 +39,7 @@ constexpr auto FLAG_MOVABLE = UINT32_C(0x00000008); // compatibility with constexpr auto FLAG_PHOTDECO = UINT32_C(0x00000008); // compatibility with old saves (decorated photons), only applies to PHOT. Having the same value as FLAG_MOVABLE is fine because they apply to different elements, and this saves space for future flags, -#define UPDATE_FUNC_ARGS Simulation* sim, int i, int x, int y, int surround_space, int nt, Particle *parts, int pmap[YRES][XRES] +#define UPDATE_FUNC_ARGS Simulation* sim, int i, int x, int y, int surround_space, int nt, Parts &parts, int pmap[YRES][XRES] #define UPDATE_FUNC_SUBCALL_ARGS sim, i, x, y, surround_space, nt, parts, pmap #define GRAPHICS_FUNC_ARGS GraphicsFuncContext &gfctx, const Particle *cpart, int nx, int ny, int *pixel_mode, int* cola, int *colr, int *colg, int *colb, int *firea, int *firer, int *fireg, int *fireb @@ -83,3 +83,4 @@ constexpr bool InBounds(int x, int y) } struct playerst; +struct Parts; diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 08154b0b5..2b4853555 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -39,7 +39,7 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2 bloc }; std::vector existingParticles; auto pasteArea = RES.OriginRect() & RectSized(partP, save->blockSize * CELL); - for (int i = 0; i <= parts_lastActiveIndex; i++) + for (int i = 0; i <= parts.lastActiveIndex; i++) { if (parts[i].type) { @@ -132,8 +132,8 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2 bloc auto i = pfree; pfree = parts[i].life; NUM_PARTS += 1; - if (i > parts_lastActiveIndex) - parts_lastActiveIndex = i; + if (i > parts.lastActiveIndex) + parts.lastActiveIndex = i; parts[i] = tempPart; elementCount[tempPart.type]++; @@ -219,7 +219,7 @@ void Simulation::Load(const GameSave *save, bool includePressure, Vec2 bloc parts[i].tmp3 = 0; } } - parts_lastActiveIndex = NPART-1; + parts.lastActiveIndex = NPART-1; force_stacking_check = true; Element_PPIP_ppip_changed = 1; @@ -992,7 +992,7 @@ void Simulation::clear_sim(void) parts[NPART-1].life = -1; pfree = 0; NUM_PARTS = 0; - parts_lastActiveIndex = 0; + parts.lastActiveIndex = 0; memset(pmap, 0, sizeof(pmap)); memset(fvx, 0, sizeof(fvx)); memset(fvy, 0, sizeof(fvy)); @@ -1890,7 +1890,7 @@ int Simulation::create_part(int p, int x, int y, int t, int v) i = p; } - if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; + if (i>parts.lastActiveIndex) parts.lastActiveIndex = i; parts[i] = elements[t].DefaultProperties; parts[i].type = t; @@ -1993,7 +1993,7 @@ void Simulation::create_gain_photon(int pp)//photons from PHOT going through GLO pfree = parts[i].life; NUM_PARTS += 1; - if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; + if (i>parts.lastActiveIndex) parts.lastActiveIndex = i; parts[i].type = PT_PHOT; parts[i].life = 680; @@ -2032,7 +2032,7 @@ void Simulation::create_cherenkov_photon(int pp)//photons from NEUT going throug pfree = parts[i].life; NUM_PARTS += 1; - if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; + if (i>parts.lastActiveIndex) parts.lastActiveIndex = i; lr = rng.between(0, 1); @@ -2210,7 +2210,7 @@ void Simulation::UpdateParticles(int start, int end) //the main particle loop function, goes over all particles. auto &sd = SimulationData::CRef(); auto &elements = sd.elements; - for (auto i = start; i < end && i <= parts_lastActiveIndex; i++) + for (auto i = start; i < end && i <= parts.lastActiveIndex; i++) { if (parts[i].type) { @@ -3363,7 +3363,7 @@ void Simulation::RecalcFreeParticles(bool do_life_dec) auto &sd = SimulationData::CRef(); auto &elements = sd.elements; //the particle loop that resets the pmap/photon maps every frame, to update them. - for (int i = 0; i <= parts_lastActiveIndex; i++) + for (int i = 0; i <= parts.lastActiveIndex; i++) { if (parts[i].type) { @@ -3431,13 +3431,13 @@ void Simulation::RecalcFreeParticles(bool do_life_dec) } if (lastPartUnused == -1) { - pfree = (parts_lastActiveIndex>=(NPART-1)) ? -1 : parts_lastActiveIndex+1; + pfree = (parts.lastActiveIndex>=(NPART-1)) ? -1 : parts.lastActiveIndex+1; } else { - parts[lastPartUnused].life = (parts_lastActiveIndex>=(NPART-1)) ? -1 : parts_lastActiveIndex+1; + parts[lastPartUnused].life = (parts.lastActiveIndex>=(NPART-1)) ? -1 : parts.lastActiveIndex+1; } - parts_lastActiveIndex = lastPartUsed; + parts.lastActiveIndex = lastPartUsed; if (elementRecount) elementRecount = false; } @@ -3446,7 +3446,7 @@ void Simulation::SimulateGoL() { auto &builtinGol = SimulationData::builtinGol; CGOL = 0; - for (int i = 0; i <= parts_lastActiveIndex; ++i) + for (int i = 0; i <= parts.lastActiveIndex; ++i) { auto &part = parts[i]; if (part.type != PT_LIFE) @@ -3652,7 +3652,7 @@ void Simulation::CheckStacking() } if (excessive_stacking_found) { - for (int i = 0; i <= parts_lastActiveIndex; i++) + for (int i = 0; i <= parts.lastActiveIndex; i++) { if (parts[i].type) { @@ -3877,7 +3877,7 @@ void Simulation::BeforeSim() // update PPIP tmp? if (Element_PPIP_ppip_changed) { - for (int i = 0; i <= parts_lastActiveIndex; i++) + for (int i = 0; i <= parts.lastActiveIndex; i++) { if (parts[i].type==PT_PPIP) { diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 22dc2ebb2..d9ae34150 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -34,6 +34,30 @@ class Renderer; class Air; class GameSave; +struct Parts +{ + std::array data; + // initialized in clear_sim + int lastActiveIndex; + + operator const Particle *() const + { + return data.data(); + } + + operator Particle *() + { + return data.data(); + } + + Parts &operator =(const Parts &other) + { + std::copy(other.data.begin(), other.data.begin() + lastActiveIndex + 1, data.begin()); + lastActiveIndex = other.lastActiveIndex; + return *this; + } +}; + struct RenderableSimulation { GravityInput gravIn; @@ -56,15 +80,12 @@ struct RenderableSimulation unsigned char bmap[YCELLS][XCELLS]; unsigned char emap[YCELLS][XCELLS]; - Particle parts[NPART]; + Parts parts; int pmap[YRES][XRES]; int photons[YRES][XRES]; int aheat_enable = 0; - // initialized in clear_sim - int parts_lastActiveIndex; - bool useLuaCallbacks = false; }; diff --git a/src/simulation/elements/EMP.cpp b/src/simulation/elements/EMP.cpp index 443dbcb14..82cb62f19 100644 --- a/src/simulation/elements/EMP.cpp +++ b/src/simulation/elements/EMP.cpp @@ -105,7 +105,7 @@ void Element_EMP_Trigger(Simulation *sim, int triggerCount) float prob_randDLAY = Probability::binomial_gte1(triggerCount, 1.0f/70); - for (int r = 0; r <=sim->parts_lastActiveIndex; r++) + for (int r = 0; r <=sim->parts.lastActiveIndex; r++) { int t = parts[r].type; auto rx = int(parts[r].x); diff --git a/src/simulation/elements/ETRD.cpp b/src/simulation/elements/ETRD.cpp index 888069817..74f991eea 100644 --- a/src/simulation/elements/ETRD.cpp +++ b/src/simulation/elements/ETRD.cpp @@ -115,7 +115,7 @@ int Element_ETRD_nearestSparkablePart(Simulation *sim, int targetId) // If the simulation contains lots of particles, check near the target position first since going through all particles will be slow. // Threshold = number of positions checked, *2 because it's likely to access memory all over the place (less cache friendly) and there's extra logic needed // TODO: probably not optimal if excessive stacking is used - if (sim->parts_lastActiveIndex > (int)deltaPos.size()*2) + if (sim->parts.lastActiveIndex > (int)deltaPos.size()*2) { for (std::vector::iterator iter = deltaPos.begin(), end = deltaPos.end(); iter != end; ++iter) { @@ -145,7 +145,7 @@ int Element_ETRD_nearestSparkablePart(Simulation *sim, int targetId) // If neighbor search didn't find a suitable particle, search all particles if (foundI < 0) { - for (int i = 0; i <= sim->parts_lastActiveIndex; i++) + for (int i = 0; i <= sim->parts.lastActiveIndex; i++) { if (parts[i].type == PT_ETRD && !parts[i].life) { @@ -164,7 +164,7 @@ int Element_ETRD_nearestSparkablePart(Simulation *sim, int targetId) { // Recalculate countLife0, and search for the closest suitable particle int countLife0 = 0; - for (int i = 0; i <= sim->parts_lastActiveIndex; i++) + for (int i = 0; i <= sim->parts.lastActiveIndex; i++) { if (parts[i].type == PT_ETRD && !parts[i].life) {