move shared vis-sim functionality to pp layer

This commit is contained in:
jacob 2026-01-10 16:04:39 -06:00
parent 4df1418aa5
commit 32938a9abe
19 changed files with 2232 additions and 2157 deletions

1258
src/pp/pp.c Normal file

File diff suppressed because it is too large Load Diff

454
src/pp/pp.h Normal file
View File

@ -0,0 +1,454 @@
////////////////////////////////////////////////////////////
//~ Key types
#define P_NilKey ((P_Key) { 0 })
Struct(P_Key)
{
u64 v;
};
////////////////////////////////////////////////////////////
//~ Shape types
Struct(P_ShapeDesc)
{
f32 radius;
f32 mass;
i32 count;
Vec2 points[8];
};
Struct(P_Shape)
{
f32 mass;
Vec2 centroid;
Vec2 center_of_mass;
f32 radius;
i32 points_count;
Vec2 points[8];
};
////////////////////////////////////////////////////////////
//~ Ent types
// TODO: Move boolean fields into bitwise property flags
// TODO: Pack efficiently, deduplicate redundant fields
Struct(P_Ent)
{
//////////////////////////////
//- Internal world state
P_Ent *next;
P_Ent *prev;
P_Ent *next_in_bin;
P_Ent *prev_in_bin;
//////////////////////////////
//- Persistent data
P_Key key;
b32 valid;
//////////////////////////////
//- Build data
f32 exists;
b32 is_player;
f32 health;
Xform last_xf;
Xform xf;
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
// TODO: Remove this (weapon testing)
i64 last_fire_ns;
b32 has_weapon;
P_Key bullet_firer;
b32 is_bullet;
Vec2 bullet_start;
Vec2 bullet_end;
b32 has_hit;
Vec2 hit_entry;
Vec2 hit_entry_normal;
//////////////////////////////
//- Solver data
Vec2 solved_v;
f32 solved_w;
};
Struct(P_EntListNode)
{
P_EntListNode *next;
P_Ent ent;
};
Struct(P_EntList)
{
P_EntListNode *first;
P_EntListNode *last;
i64 count;
};
Struct(P_EntBin)
{
P_Ent *first;
P_Ent *last;
};
////////////////////////////////////////////////////////////
//~ World types
Struct(P_World)
{
u64 seed;
i64 tick;
i64 time_ns;
i64 ents_count;
P_Ent *first_ent;
P_Ent *last_ent;
i64 ent_bins_count;
P_EntBin *ent_bins;
u8 *tiles;
};
Enum(P_DeltaKind)
{
P_DeltaKind_Reset,
P_DeltaKind_RawEnt,
P_DeltaKind_RawTiles,
P_DeltaKind_Tile,
};
Struct(P_Delta)
{
P_DeltaKind kind;
P_Ent ent;
u8 *raw_tiles;
P_TileKind tile_kind;
Rng2I32 tile_range;
};
Struct(P_DeltaNode)
{
P_DeltaNode *next;
P_Delta delta;
};
Struct(P_Snapshot)
{
u64 seed;
i64 tick;
i64 time_ns;
i64 deltas_count;
P_DeltaNode *first_delta_node;
P_DeltaNode *last_delta_node;
};
Struct(P_SnapshotNode)
{
P_SnapshotNode *next;
P_Snapshot snapshot;
};
////////////////////////////////////////////////////////////
//~ Collision types
Struct(P_SupportPoint)
{
Vec2 p;
u32 id; // Index of the originating piont in the shape
};
Struct(P_CollisionPoint)
{
Vec2 p;
f32 separation;
u32 id; // Based on polygon edge-to-edge
};
Struct(P_MenkowskiPoint)
{
Vec2 p; // Menkowski difference point
P_SupportPoint s0; // Support point of first shape in dir
P_SupportPoint s1; // Support point of second shape in -dir
};
Struct(P_MenkowskiSimplex)
{
i32 count;
P_MenkowskiPoint a, b, c;
};
Struct(P_ClippedLine)
{
Vec2 a0_clipped, b0_clipped;
Vec2 a1_clipped, b1_clipped;
};
Struct(P_CollisionResult)
{
// Collision manifold
i32 collision_points_count;
P_CollisionPoint collision_points[2];
Vec2 collision_normal;
// Closest points
Vec2 closest_p0;
Vec2 closest_p1;
};
Struct(P_RaycastResult)
{
b32 is_intersecting;
Vec2 p;
Vec2 normal;
};
////////////////////////////////////////////////////////////
//~ Constraint types
Struct(P_ContactPoint)
{
Vec2 vcp0;
Vec2 vcp1;
f32 starting_separation;
f32 inv_normal_mass;
f32 inv_tangent_mass;
u32 id;
f32 solved_normal_impulse;
f32 solved_tangent_impulse;
};
Struct(P_Constraint)
{
i64 last_touched_tick;
P_Key ent0;
P_Key ent1;
Vec2 static_center0;
Vec2 static_center1;
f32 inv_m0;
f32 inv_m1;
f32 inv_i0;
f32 inv_i1;
Vec2 normal;
f32 friction;
i32 points_count;
P_ContactPoint points[2];
};
////////////////////////////////////////////////////////////
//~ Debug visualization types
Enum(P_DebugDrawKind)
{
P_DebugDrawKind_Point,
P_DebugDrawKind_Line,
P_DebugDrawKind_Rect,
P_DebugDrawKind_Shape,
};
Struct(P_DebugDrawNode)
{
P_DebugDrawNode *next;
P_DebugDrawKind kind;
u32 srgb32;
union
{
struct
{
Vec2 p;
} point;
struct
{
Vec2 p0;
Vec2 p1;
} line;
Rng2 rect;
P_Shape shape;
};
};
////////////////////////////////////////////////////////////
//~ Command types
Enum(P_CmdKind)
{
P_CmdKind_Nop,
P_CmdKind_Save,
P_CmdKind_Delta,
P_CmdKind_Control,
};
Struct(P_Cmd)
{
P_CmdKind kind;
// Delta
P_Delta delta;
// Control
P_Key target;
Vec2 move;
Vec2 look;
b32 fire_held;
i32 fire_presses;
};
Struct(P_CmdNode)
{
P_CmdNode *next;
P_Cmd cmd;
};
Struct(P_InputState)
{
Arena *arena;
P_CmdNode *first_cmd_node;
P_CmdNode *last_cmd_node;
u64 cmds_count;
};
Struct(P_OutputState)
{
Arena *arena;
P_SnapshotNode *first_snapshot_node;
P_SnapshotNode *last_snapshot_node;
u64 snapshots_count;
P_DebugDrawNode *first_debug_draw_node;
P_DebugDrawNode *last_debug_draw_node;
i64 debug_draw_nodes_count;
};
////////////////////////////////////////////////////////////
//~ State types
Struct(P_Ctx)
{
//- Sim input
TicketMutex sim_input_back_tm;
i32 sim_input_back_idx;
P_InputState sim_input_states[2];
//- Sim output
TicketMutex sim_output_back_tm;
i32 sim_output_back_idx;
P_OutputState sim_output_states[2];
};
Struct(P_ThreadLocalCtx)
{
Arena *debug_arena;
b32 debug_draw_enabled;
P_DebugDrawNode *first_debug_draw_node;
P_DebugDrawNode *last_debug_draw_node;
i64 debug_draw_nodes_count;
};
extern P_Ctx P;
extern ThreadLocal P_ThreadLocalCtx P_tl;
////////////////////////////////////////////////////////////
//~ Bootstrap
void P_Bootstrap(void);
////////////////////////////////////////////////////////////
//~ Nil helpers
b32 P_IsKeyNil(P_Key key);
b32 P_IsEntNil(P_Ent *ent);
b32 P_MatchKey(P_Key a, P_Key b);
////////////////////////////////////////////////////////////
//~ Key helpers
P_Key P_RandKey(void);
#define P_FmtKey(key) FmtHandle((key).v)
////////////////////////////////////////////////////////////
//~ Tile helpers
String P_NameFromTileKind(P_TileKind kind);
////////////////////////////////////////////////////////////
//~ Delta helpers
void P_UpdateWorldFromDelta(Arena *arena, P_World *world, P_Delta *delta);
////////////////////////////////////////////////////////////
//~ Shape helpers
P_Shape P_ShapeFromDescEx(P_ShapeDesc desc);
#define P_ShapeFromDesc(...) P_ShapeFromDescEx((P_ShapeDesc) { __VA_ARGS__ })
P_Shape P_MulXformShape(Xform xf, P_Shape shape);
Rng2 P_BoundingBoxFromShape(P_Shape shape);
P_Shape P_LocalShapeFromEnt(P_Ent *ent);
P_Shape P_WorldShapeFromEnt(P_Ent *ent);
////////////////////////////////////////////////////////////
//~ Collision
P_SupportPoint P_SupportPointFromShapeEx(P_Shape shape, Vec2 dir, i32 ignore_idx);
P_SupportPoint P_SupportPointFromShape(P_Shape shape, Vec2 dir);
P_MenkowskiPoint P_MenkowskiPointFromShapes(P_Shape shape0, P_Shape shape1, Vec2 dir);
P_ClippedLine P_ClipLineToLine(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal);
Vec2 P_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal);
P_CollisionResult P_CollisionResultFromShapes(P_Shape shape0, P_Shape shape1);
P_RaycastResult P_RaycastShape(P_Shape shape, Vec2 ray_start, Vec2 ray_dir);
Vec2 P_EdgePointFromShape(P_Shape shape, Vec2 dir);
////////////////////////////////////////////////////////////
//~ Lookup helpers
P_Ent *P_EntFromKey(P_World *world, P_Key key);
////////////////////////////////////////////////////////////
//~ Iteration helpers
P_Ent *P_FirstEnt(P_World *world);
P_Ent *P_NextEnt(P_Ent *e);
////////////////////////////////////////////////////////////
//~ List helpers
P_Ent *P_PushTempEnt(Arena *arena, P_EntList *list);
void P_SpawnEntsFromList(Arena *arena, P_World *world, P_EntList ents);
////////////////////////////////////////////////////////////
//~ Debug draw
void P_DebugDrawPoint(Vec2 p, Vec4 srgb);
void P_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
void P_DebugDrawRect(Rng2 rect, Vec4 srgb);
void P_DebugDrawShape(P_Shape shape, Vec4 srgb);

View File

@ -5,8 +5,23 @@
@EmbedDir P_Resources pp_res @EmbedDir P_Resources pp_res
//////////////////////////////
//- Api
@IncludeC pp_shared.cgh
@IncludeG pp_shared.cgh
@IncludeC pp.h
@IncludeC pp_transcode.h
@Bootstrap P_Bootstrap
////////////////////////////// //////////////////////////////
//- Impl //- Impl
@DefaultDownstream Any pp_vis @IncludeC pp_shared.cg
@IncludeG pp_shared.cg
@IncludeC pp.c
@IncludeC pp_transcode.c
@DefaultDownstream Any pp_sim @DefaultDownstream Any pp_sim
@DefaultDownstream Any pp_vis

27
src/pp/pp_shared.cg Normal file
View File

@ -0,0 +1,27 @@
////////////////////////////////////////////////////////////
//~ Tile helpers
i32 P_TileIdxFromTilePos(Vec2 p)
{
i32 x = ClampI32(FloorF32(p.x), 0, P_TilesPitch - 1);
i32 y = ClampI32(FloorF32(p.y), 0, P_TilesPitch - 1);
i32 result = x + (y * P_TilesPitch);
return result;
}
#if IsLanguageC
String P_TileNameFromKind(P_TileKind kind)
{
PERSIST Readonly String tile_names[P_TileKind_COUNT] = {
#define X(name, ...) [P_TileKind_##name] = CompLit(#name),
P_TilesXMacro(X)
#undef X
};
String result = Zi;
if (kind >= 0 && kind < countof(tile_names))
{
result = tile_names[kind];
}
return result;
}
#endif

35
src/pp/pp_shared.cgh Normal file
View File

@ -0,0 +1,35 @@
////////////////////////////////////////////////////////////
//~ Tile types
#define P_WorldPitch 64.0
#define P_TilesPerMeter 2.0
#define P_TilesPerSqMeter (V_TilesPerMeter * V_TilesPerMeter)
#define P_TilesPitch (P_WorldPitch * P_TilesPerMeter)
#define P_TilesCount (P_TilesPitch * P_TilesPitch)
#define P_TilesXMacro(X) \
X(Empty) \
X(Tile) \
X(Carpet) \
X(Wall) \
/* -------------------- */
//- Tiles kinds enum
Enum(P_TileKind)
{
#define X(name, ...) P_TileKind_##name,
P_TilesXMacro(X)
#undef X
P_TileKind_COUNT
};
////////////////////////////////////////////////////////////
//~ Tile helpers
i32 P_TileIdxFromTilePos(Vec2 p);
#if IsLanguageC
String P_TileNameFromKind(P_TileKind kind);
#endif

View File

@ -9,11 +9,7 @@
////////////////////////////// //////////////////////////////
//- Api //- Api
@IncludeC pp_sim_shared.cgh
@IncludeG pp_sim_shared.cgh
@IncludeC pp_sim_core.h @IncludeC pp_sim_core.h
@IncludeC pp_sim_transcode.h
@Bootstrap S_Bootstrap @Bootstrap S_Bootstrap
@ -21,6 +17,3 @@
//- Impl //- Impl
@IncludeC pp_sim_core.c @IncludeC pp_sim_core.c
@IncludeC pp_sim_transcode.c
@IncludeC pp_sim_shared.cg
@IncludeG pp_sim_shared.cg

File diff suppressed because it is too large Load Diff

View File

@ -1,382 +1,13 @@
////////////////////////////////////////////////////////////
//~ Key types
#define S_NilKey ((S_Key) { 0 })
Struct(S_Key)
{
u64 v;
};
////////////////////////////////////////////////////////////
//~ Shape types
Struct(S_ShapeDesc)
{
f32 radius;
f32 mass;
i32 count;
Vec2 points[8];
};
Struct(S_Shape)
{
f32 mass;
Vec2 centroid;
Vec2 center_of_mass;
f32 radius;
i32 points_count;
Vec2 points[8];
};
////////////////////////////////////////////////////////////
//~ Ent types
// TODO: Move boolean fields into bitwise property flags
// TODO: Pack efficiently, deduplicate redundant fields
Struct(S_Ent)
{
//////////////////////////////
//- Internal world state
S_Ent *next;
S_Ent *prev;
S_Ent *next_in_bin;
S_Ent *prev_in_bin;
//////////////////////////////
//- Persistent data
S_Key key;
b32 valid;
//////////////////////////////
//- Build data
f32 exists;
b32 is_player;
f32 health;
Xform last_xf;
Xform xf;
Vec2 move;
Vec2 look;
f32 fire_held;
f32 fire_presses;
// TODO: Remove this (weapon testing)
i64 last_fire_ns;
b32 has_weapon;
S_Key bullet_firer;
b32 is_bullet;
Vec2 bullet_start;
Vec2 bullet_end;
b32 has_hit;
Vec2 hit_entry;
Vec2 hit_entry_normal;
//////////////////////////////
//- Solver data
Vec2 solved_v;
f32 solved_w;
};
Struct(S_EntListNode)
{
S_EntListNode *next;
S_Ent ent;
};
Struct(S_EntList)
{
S_EntListNode *first;
S_EntListNode *last;
i64 count;
};
Struct(S_EntBin)
{
S_Ent *first;
S_Ent *last;
};
////////////////////////////////////////////////////////////
//~ Collision types
Struct(S_SupportPoint)
{
Vec2 p;
u32 id; // Index of the originating piont in the shape
};
Struct(S_CollisionPoint)
{
Vec2 p;
f32 separation;
u32 id; // Based on polygon edge-to-edge
};
Struct(S_MenkowskiPoint)
{
Vec2 p; // Menkowski difference point
S_SupportPoint s0; // Support point of first shape in dir
S_SupportPoint s1; // Support point of second shape in -dir
};
Struct(S_MenkowskiSimplex)
{
i32 count;
S_MenkowskiPoint a, b, c;
};
Struct(S_ClippedLine)
{
Vec2 a0_clipped, b0_clipped;
Vec2 a1_clipped, b1_clipped;
};
Struct(S_CollisionResult)
{
// Collision manifold
i32 collision_points_count;
S_CollisionPoint collision_points[2];
Vec2 collision_normal;
// Closest points
Vec2 closest_p0;
Vec2 closest_p1;
};
Struct(S_RaycastResult)
{
b32 is_intersecting;
Vec2 p;
Vec2 normal;
};
////////////////////////////////////////////////////////////
//~ Constraint types
Struct(S_ContactPoint)
{
Vec2 vcp0;
Vec2 vcp1;
f32 starting_separation;
f32 inv_normal_mass;
f32 inv_tangent_mass;
u32 id;
f32 solved_normal_impulse;
f32 solved_tangent_impulse;
};
Struct(S_Constraint)
{
i64 last_touched_tick;
S_Key ent0;
S_Key ent1;
Vec2 static_center0;
Vec2 static_center1;
f32 inv_m0;
f32 inv_m1;
f32 inv_i0;
f32 inv_i1;
Vec2 normal;
f32 friction;
i32 points_count;
S_ContactPoint points[2];
};
////////////////////////////////////////////////////////////
//~ World types
Struct(S_World)
{
u64 seed;
i64 tick;
i64 time_ns;
i64 ents_count;
S_Ent *first_ent;
S_Ent *last_ent;
i64 ent_bins_count;
S_EntBin *ent_bins;
u8 *tiles;
};
Enum(S_DeltaKind)
{
S_DeltaKind_Reset,
S_DeltaKind_RawEnt,
S_DeltaKind_RawTiles,
S_DeltaKind_Tile,
};
Struct(S_Delta)
{
S_DeltaKind kind;
S_Ent ent;
u8 *raw_tiles;
S_TileKind tile_kind;
Rng2I32 tile_range;
};
Struct(S_DeltaNode)
{
S_DeltaNode *next;
S_Delta delta;
};
Struct(S_Snapshot)
{
u64 seed;
i64 tick;
i64 time_ns;
i64 deltas_count;
S_DeltaNode *first_delta_node;
S_DeltaNode *last_delta_node;
};
Struct(S_SnapshotNode)
{
S_SnapshotNode *next;
S_Snapshot snapshot;
};
////////////////////////////////////////////////////////////
//~ Command types
Enum(S_CmdKind)
{
S_CmdKind_Nop,
S_CmdKind_Save,
S_CmdKind_Delta,
S_CmdKind_Control,
};
Struct(S_Cmd)
{
S_CmdKind kind;
// Delta
S_Delta delta;
// Control
S_Key target;
Vec2 move;
Vec2 look;
b32 fire_held;
i32 fire_presses;
};
Struct(S_CmdNode)
{
S_CmdNode *next;
S_Cmd cmd;
};
////////////////////////////////////////////////////////////
//~ Debug visualization types
Enum(S_DebugDrawKind)
{
S_DebugDrawKind_Point,
S_DebugDrawKind_Line,
S_DebugDrawKind_Rect,
S_DebugDrawKind_Shape,
};
Struct(S_DebugDrawDesc)
{
S_DebugDrawKind kind;
u32 srgb32;
union
{
struct
{
Vec2 p;
} point;
struct
{
Vec2 p0;
Vec2 p1;
} line;
Rng2 rect;
S_Shape shape;
};
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ State types //~ State types
Struct(S_InputState)
{
Arena *arena;
S_CmdNode *first_cmd_node;
S_CmdNode *last_cmd_node;
u64 cmds_count;
};
Struct(S_OutputState)
{
Arena *arena;
S_SnapshotNode *first_snapshot_node;
S_SnapshotNode *last_snapshot_node;
u64 snapshots_count;
u64 debug_draw_descs_count;
S_DebugDrawDesc *debug_draw_descs;
};
Struct(S_Ctx) Struct(S_Ctx)
{ {
Atomic32 shutdown; Atomic32 shutdown;
Fence shutdown_fence; Fence shutdown_fence;
b32 debug_draw_enabled;
Arena *debug_draw_descs_arena;
//- Sim input
TicketMutex input_back_tm;
i32 input_back_idx;
S_InputState input_states[2];
//- Sim output
TicketMutex output_back_tm;
i32 output_back_idx;
S_OutputState output_states[2];
};
Struct(S_ThreadLocalCtx)
{
b32 is_sim_tick_thread;
}; };
extern S_Ctx S; extern S_Ctx S;
extern ThreadLocal S_ThreadLocalCtx S_tl;
extern Readonly S_Ent S_NilEnt;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Bootstrap //~ Bootstrap
@ -384,81 +15,6 @@ extern Readonly S_Ent S_NilEnt;
void S_Bootstrap(void); void S_Bootstrap(void);
void S_Shutdown(void); void S_Shutdown(void);
////////////////////////////////////////////////////////////
//~ Nil helpers
b32 S_IsKeyNil(S_Key key);
b32 S_IsEntNil(S_Ent *ent);
b32 S_MatchKey(S_Key a, S_Key b);
////////////////////////////////////////////////////////////
//~ Key helpers
S_Key S_RandKey(void);
#define S_FmtKey(key) FmtHandle((key).v)
////////////////////////////////////////////////////////////
//~ Tile helpers
String S_NameFromTileKind(S_TileKind kind);
////////////////////////////////////////////////////////////
//~ Delta helpers
void S_UpdateWorldFromDelta(Arena *arena, S_World *world, S_Delta *delta);
////////////////////////////////////////////////////////////
//~ Shape helpers
S_Shape S_ShapeFromDescEx(S_ShapeDesc desc);
#define S_ShapeFromDesc(...) S_ShapeFromDescEx((S_ShapeDesc) { __VA_ARGS__ })
S_Shape S_MulXformShape(Xform xf, S_Shape shape);
Rng2 S_BoundingBoxFromShape(S_Shape shape);
S_Shape S_LocalShapeFromEnt(S_Ent *ent);
S_Shape S_WorldShapeFromEnt(S_Ent *ent);
////////////////////////////////////////////////////////////
//~ Collision
S_SupportPoint S_SupportPointFromShapeEx(S_Shape shape, Vec2 dir, i32 ignore_idx);
S_SupportPoint S_SupportPointFromShape(S_Shape shape, Vec2 dir);
S_MenkowskiPoint S_MenkowskiPointFromShapes(S_Shape shape0, S_Shape shape1, Vec2 dir);
S_ClippedLine S_ClipLineToLine(Vec2 a0, Vec2 b0, Vec2 a1, Vec2 b1, Vec2 normal);
Vec2 S_ClipPointToLine(Vec2 a, Vec2 b, Vec2 p, Vec2 normal);
S_CollisionResult S_CollisionResultFromShapes(S_Shape shape0, S_Shape shape1);
S_RaycastResult S_RaycastShape(S_Shape shape, Vec2 ray_start, Vec2 ray_dir);
Vec2 S_EdgePointFromShape(S_Shape shape, Vec2 dir);
////////////////////////////////////////////////////////////
//~ Lookup helpers
S_Ent *S_EntFromKey(S_World *world, S_Key key);
////////////////////////////////////////////////////////////
//~ Iteration helpers
S_Ent *S_FirstEnt(S_World *world);
S_Ent *S_NextEnt(S_Ent *e);
////////////////////////////////////////////////////////////
//~ List helpers
S_Ent *S_PushTempEnt(Arena *arena, S_EntList *list);
void S_SpawnEntsFromList(Arena *arena, S_World *world, S_EntList ents);
////////////////////////////////////////////////////////////
//~ Debug draw
void S_DebugDrawPoint(Vec2 p, Vec4 srgb);
void S_DebugDrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
void S_DebugDrawRect(Rng2 rect, Vec4 srgb);
void S_DebugDrawShape(S_Shape shape, Vec4 srgb);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Sim tick //~ Sim tick

View File

@ -1,27 +0,0 @@
////////////////////////////////////////////////////////////
//~ Tile helpers
i32 S_TileIdxFromTilePos(Vec2 p)
{
i32 x = ClampI32(FloorF32(p.x), 0, S_TilesPitch - 1);
i32 y = ClampI32(FloorF32(p.y), 0, S_TilesPitch - 1);
i32 result = x + (y * S_TilesPitch);
return result;
}
#if IsLanguageC
String S_TileNameFromKind(S_TileKind kind)
{
PERSIST Readonly String tile_names[S_TileKind_COUNT] = {
#define X(name, ...) [S_TileKind_##name] = CompLit(#name),
S_TilesXMacro(X)
#undef X
};
String result = Zi;
if (kind >= 0 && kind < countof(tile_names))
{
result = tile_names[kind];
}
return result;
}
#endif

View File

@ -1,35 +0,0 @@
////////////////////////////////////////////////////////////
//~ Tile types
#define S_WorldPitch 64.0
#define S_TilesPerMeter 2.0
#define S_TilesPerSqMeter (V_TilesPerMeter * V_TilesPerMeter)
#define S_TilesPitch (S_WorldPitch * S_TilesPerMeter)
#define S_TilesCount (S_TilesPitch * S_TilesPitch)
#define S_TilesXMacro(X) \
X(Empty) \
X(Tile) \
X(Carpet) \
X(Wall) \
/* -------------------- */
//- Tiles kinds enum
Enum(S_TileKind)
{
#define X(name, ...) S_TileKind_##name,
S_TilesXMacro(X)
#undef X
S_TileKind_COUNT
};
////////////////////////////////////////////////////////////
//~ Tile helpers
i32 S_TileIdxFromTilePos(Vec2 p);
#if IsLanguageC
String S_TileNameFromKind(S_TileKind kind);
#endif

View File

@ -1,30 +0,0 @@
////////////////////////////////////////////////////////////
//~ Transcode types
Enum(S_Tv)
{
S_Tv_None = 0,
S_Tv_Initial = 1,
S_Tv_COUNT
};
#define S_Tv_Latest (S_Tv_COUNT - 1)
Struct(S_UnpackedWorld)
{
S_Tv version;
u64 seed;
i64 tick;
i64 time_ns;
S_EntList ents;
u8 *tiles;
};
////////////////////////////////////////////////////////////
//~ Transcode
String S_PackWorld(Arena *arena, S_World *src_world);
S_UnpackedWorld S_UnpackWorld(Arena *arena, String packed);

View File

@ -1,19 +1,13 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Transcode //~ Transcode
String P_PackWorld(Arena *arena, P_World *src_world)
// FIXME: Header
String S_PackWorld(Arena *arena, S_World *src_world)
{ {
String result = Zi; String result = Zi;
result.text = ArenaNext(arena, u8); result.text = ArenaNext(arena, u8);
TempArena scratch = BeginScratch(arena); TempArena scratch = BeginScratch(arena);
result.len += StringF(arena, "version: %F\n", FmtUint(S_Tv_Latest)).len; result.len += StringF(arena, "version: %F\n", FmtUint(P_Tv_Latest)).len;
result.len += StringF(arena, "\n").len; result.len += StringF(arena, "\n").len;
result.len += StringF(arena, "seed: 0x%F\n", FmtHex(src_world->seed)).len; result.len += StringF(arena, "seed: 0x%F\n", FmtHex(src_world->seed)).len;
@ -24,7 +18,7 @@ String S_PackWorld(Arena *arena, S_World *src_world)
// FIXME: Precision // FIXME: Precision
result.len += PushString(arena, Lit("\nentities:\n")).len; result.len += PushString(arena, Lit("\nentities:\n")).len;
result.len += PushString(arena, Lit("{\n")).len; result.len += PushString(arena, Lit("{\n")).len;
for (S_Ent *ent = S_FirstEnt(src_world); ent->valid; ent = S_NextEnt(ent)) for (P_Ent *ent = P_FirstEnt(src_world); ent->valid; ent = P_NextEnt(ent))
{ {
// TODO: Pack bullets // TODO: Pack bullets
if (!ent->is_bullet) if (!ent->is_bullet)
@ -60,7 +54,7 @@ String S_PackWorld(Arena *arena, S_World *src_world)
result.len += PushString(arena, Lit("\ntiles:\n")).len; result.len += PushString(arena, Lit("\ntiles:\n")).len;
result.len += PushString(arena, Lit("{\n")).len; result.len += PushString(arena, Lit("{\n")).len;
{ {
String tiles_str = Base64FromString(scratch.arena, STRING(S_TilesCount, src_world->tiles)); String tiles_str = Base64FromString(scratch.arena, STRING(P_TilesCount, src_world->tiles));
u64 tile_chars_per_line = 128; u64 tile_chars_per_line = 128;
u64 tile_char_pos = 0; u64 tile_char_pos = 0;
while (tile_char_pos < tiles_str.len) while (tile_char_pos < tiles_str.len)
@ -80,15 +74,15 @@ String S_PackWorld(Arena *arena, S_World *src_world)
return result; return result;
} }
S_UnpackedWorld S_UnpackWorld(Arena *arena, String packed) P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
{ {
S_UnpackedWorld result = Zi; P_UnpackedWorld result = Zi;
TempArena scratch = BeginScratch(arena); TempArena scratch = BeginScratch(arena);
CR_Item *root = CR_ItemFromString(scratch.arena, packed); CR_Item *root = CR_ItemFromString(scratch.arena, packed);
// Unpack version // Unpack version
S_Tv version = 0; P_Tv version = 0;
for (CR_Item *root_item = root->first; root_item; root_item = root_item->next) for (CR_Item *root_item = root->first; root_item; root_item = root_item->next)
{ {
if (MatchString(root_item->name, Lit("version"))) if (MatchString(root_item->name, Lit("version")))
@ -119,8 +113,8 @@ S_UnpackedWorld S_UnpackWorld(Arena *arena, String packed)
{ {
for (CR_Item *ent_item = top_item->first; ent_item; ent_item = ent_item->next) for (CR_Item *ent_item = top_item->first; ent_item; ent_item = ent_item->next)
{ {
S_Ent *ent = S_PushTempEnt(arena, &result.ents); P_Ent *ent = P_PushTempEnt(arena, &result.ents);
ent->key = (S_Key) { .v = CR_IntFromString(ent_item->name) }; ent->key = (P_Key) { .v = CR_IntFromString(ent_item->name) };
for (CR_Item *attr = ent_item->first; attr; attr = attr->next) for (CR_Item *attr = ent_item->first; attr; attr = attr->next)
{ {
if (MatchString(attr->name, Lit("props"))) if (MatchString(attr->name, Lit("props")))
@ -175,7 +169,7 @@ S_UnpackedWorld S_UnpackWorld(Arena *arena, String packed)
tiles_base64.len += PushString(scratch.arena, tile_item->value).len; tiles_base64.len += PushString(scratch.arena, tile_item->value).len;
} }
} }
if (StringLenFromBase64Len(tiles_base64.len) == S_TilesCount) if (StringLenFromBase64Len(tiles_base64.len) == P_TilesCount)
{ {
result.tiles = StringFromBase64(arena, tiles_base64).text; result.tiles = StringFromBase64(arena, tiles_base64).text;
} }
@ -183,7 +177,7 @@ S_UnpackedWorld S_UnpackWorld(Arena *arena, String packed)
if (!result.tiles) if (!result.tiles)
{ {
result.tiles = PushStructs(arena, u8, S_TilesCount); result.tiles = PushStructs(arena, u8, P_TilesCount);
} }
EndScratch(scratch); EndScratch(scratch);

30
src/pp/pp_transcode.h Normal file
View File

@ -0,0 +1,30 @@
////////////////////////////////////////////////////////////
//~ Transcode types
Enum(P_Tv)
{
P_Tv_None = 0,
P_Tv_Initial = 1,
P_Tv_COUNT
};
#define P_Tv_Latest (P_Tv_COUNT - 1)
Struct(P_UnpackedWorld)
{
P_Tv version;
u64 seed;
i64 tick;
i64 time_ns;
P_EntList ents;
u8 *tiles;
};
////////////////////////////////////////////////////////////
//~ Transcode
String P_PackWorld(Arena *arena, P_World *src_world);
P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed);

View File

@ -4,7 +4,6 @@
//- Dependencies //- Dependencies
@Dep pp @Dep pp
@Dep pp_sim
@Dep sprite @Dep sprite
@Dep gpu @Dep gpu
@Dep glyph_cache @Dep glyph_cache

View File

@ -41,10 +41,10 @@ V_Cmd *V_PushVisCmd(String name)
return cmd; return cmd;
} }
S_Cmd *V_PushSimCmd(S_CmdKind kind) P_Cmd *V_PushSimCmd(P_CmdKind kind)
{ {
V_Frame *frame = V_CurrentFrame(); V_Frame *frame = V_CurrentFrame();
S_CmdNode *n = PushStruct(frame->arena, S_CmdNode); P_CmdNode *n = PushStruct(frame->arena, P_CmdNode);
n->cmd.kind = kind; n->cmd.kind = kind;
SllQueuePush(frame->first_sim_cmd_node, frame->last_sim_cmd_node, n); SllQueuePush(frame->first_sim_cmd_node, frame->last_sim_cmd_node, n);
++frame->sim_cmds_count; ++frame->sim_cmds_count;
@ -198,7 +198,7 @@ void V_DrawPoly(Vec2Array points, Vec4 srgb, V_DrawFlag flags)
} }
} }
void V_DrawShape(S_Shape shape, Vec4 srgb, i32 detail, V_DrawFlag flags) void V_DrawShape(P_Shape shape, Vec4 srgb, i32 detail, V_DrawFlag flags)
{ {
if (shape.radius == 0) if (shape.radius == 0)
{ {
@ -218,7 +218,7 @@ void V_DrawShape(S_Shape shape, Vec4 srgb, i32 detail, V_DrawFlag flags)
{ {
f32 rad = ((f32)i / (f32)detail) * Tau; f32 rad = ((f32)i / (f32)detail) * Tau;
Vec2 dir = Vec2FromAngle(rad); Vec2 dir = Vec2FromAngle(rad);
Vec2 sp = S_SupportPointFromShape(shape, dir).p; Vec2 sp = P_SupportPointFromShape(shape, dir).p;
draw_points.points[i] = sp; draw_points.points[i] = sp;
} }
V_DrawPoly(draw_points, srgb, flags); V_DrawPoly(draw_points, srgb, flags);
@ -255,7 +255,7 @@ void V_DrawRect(Rng2 rect, Vec4 srgb, V_DrawFlag flags)
void V_DrawPoint(Vec2 p, Vec4 srgb) void V_DrawPoint(Vec2 p, Vec4 srgb)
{ {
S_Shape ui_shape = S_ShapeFromDesc( P_Shape ui_shape = P_ShapeFromDesc(
.count = 1, .count = 1,
.points = { p }, .points = { p },
.radius = 5 .radius = 5
@ -326,7 +326,7 @@ void V_TickForever(WaveLaneCtx *lane)
Arena *perm = PermArena(); Arena *perm = PermArena();
G_ArenaHandle gpu_perm = G_PermArena(); G_ArenaHandle gpu_perm = G_PermArena();
const i32 world_pitch = S_WorldPitch; const i32 world_pitch = P_WorldPitch;
const f32 zoom_rate = 1.50; const f32 zoom_rate = 1.50;
const f32 min_zoom = 0.03; const f32 min_zoom = 0.03;
const f32 max_zoom = 15.0; const f32 max_zoom = 15.0;
@ -336,17 +336,17 @@ void V_TickForever(WaveLaneCtx *lane)
//- Init vis state //- Init vis state
Arena *sim_debug_arena = AcquireArena(Gibi(64)); Arena *sim_debug_arena = AcquireArena(Gibi(64));
u64 sim_debug_draw_descs_count = 0; P_DebugDrawNode *first_sim_debug_draw_node = 0;
S_DebugDrawDesc *sim_debug_draw_descs = 0; P_DebugDrawNode *last_sim_debug_draw_node = 0;
Arena *world_arena = AcquireArena(Gibi(64)); Arena *world_arena = AcquireArena(Gibi(64));
S_World *world = PushStruct(world_arena, S_World); P_World *world = PushStruct(world_arena, P_World);
world->ent_bins_count = Kibi(16); world->ent_bins_count = Kibi(16);
world->ent_bins = PushStructs(world_arena, S_EntBin, world->ent_bins_count); world->ent_bins = PushStructs(world_arena, P_EntBin, world->ent_bins_count);
world->tiles = PushStructs(world_arena, u8, S_TilesCount); world->tiles = PushStructs(world_arena, u8, P_TilesCount);
Vec2I32 tiles_dims = VEC2I32(S_TilesPitch, S_TilesPitch); Vec2I32 tiles_dims = VEC2I32(P_TilesPitch, P_TilesPitch);
Vec2I32 cells_dims = VEC2I32(V_CellsPerMeter * S_WorldPitch, V_CellsPerMeter * S_WorldPitch); Vec2I32 cells_dims = VEC2I32(V_CellsPerMeter * P_WorldPitch, V_CellsPerMeter * P_WorldPitch);
// Init gpu state // Init gpu state
G_ResourceHandle gpu_state = Zi; G_ResourceHandle gpu_state = Zi;
@ -489,6 +489,7 @@ void V_TickForever(WaveLaneCtx *lane)
while (!shutdown) while (!shutdown)
{ {
shutdown = Atomic32Fetch(&V.shutdown); shutdown = Atomic32Fetch(&V.shutdown);
P_tl.debug_draw_enabled = 1;
////////////////////////////// //////////////////////////////
//- Begin frame //- Begin frame
@ -532,9 +533,9 @@ void V_TickForever(WaveLaneCtx *lane)
frame->dt = SecondsFromNs(frame->dt_ns); frame->dt = SecondsFromNs(frame->dt_ns);
frame->rand = last_frame->rand; frame->rand = last_frame->rand;
if (S_IsKeyNil(V.player_key)) if (P_IsKeyNil(V.player_key))
{ {
V.player_key = S_RandKey(); V.player_key = P_RandKey();
} }
////////////////////////////// //////////////////////////////
@ -633,17 +634,17 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Pop sim output //- Pop sim output
S_OutputState *sim_output = 0; P_OutputState *sim_output = 0;
LockTicketMutex(&S.output_back_tm); LockTicketMutex(&P.sim_output_back_tm);
{ {
sim_output = &S.output_states[S.output_back_idx]; sim_output = &P.sim_output_states[P.sim_output_back_idx];
++S.output_back_idx; ++P.sim_output_back_idx;
if (S.output_back_idx >= countof(S.output_states)) if (P.sim_output_back_idx >= countof(P.sim_output_states))
{ {
S.output_back_idx = 0; P.sim_output_back_idx = 0;
} }
} }
UnlockTicketMutex(&S.output_back_tm); UnlockTicketMutex(&P.sim_output_back_tm);
////////////////////////////// //////////////////////////////
//- Apply sim snapshots //- Apply sim snapshots
@ -653,59 +654,45 @@ void V_TickForever(WaveLaneCtx *lane)
b32 received_unseen_tick = 0; b32 received_unseen_tick = 0;
b32 tiles_dirty = 0; b32 tiles_dirty = 0;
b32 should_clear_particles = 0; b32 should_clear_particles = 0;
for (S_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next) for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next)
{ {
S_Snapshot *snapshot = &n->snapshot; P_Snapshot *snapshot = &n->snapshot;
if (snapshot->tick > world->tick) if (snapshot->tick > world->tick)
{ {
world->seed = snapshot->seed; world->seed = snapshot->seed;
world->tick = snapshot->tick; world->tick = snapshot->tick;
world->time_ns = snapshot->time_ns; world->time_ns = snapshot->time_ns;
for (S_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next) for (P_DeltaNode *dn = snapshot->first_delta_node; dn; dn = dn->next)
{ {
S_Delta *delta = &dn->delta; P_Delta *delta = &dn->delta;
if (delta->kind == S_DeltaKind_Reset) if (delta->kind == P_DeltaKind_Reset)
{ {
tiles_dirty = 1; tiles_dirty = 1;
should_clear_particles = 1; should_clear_particles = 1;
} }
if (delta->kind == S_DeltaKind_RawTiles || delta->kind == S_DeltaKind_Tile) if (delta->kind == P_DeltaKind_RawTiles || delta->kind == P_DeltaKind_Tile)
{ {
tiles_dirty = 1; tiles_dirty = 1;
} }
S_UpdateWorldFromDelta(world_arena, world, delta); P_UpdateWorldFromDelta(world_arena, world, delta);
} }
received_unseen_tick = 1; received_unseen_tick = 1;
} }
} }
//////////////////////////////
//- Copy sim debug info
if (received_unseen_tick)
{
ResetArena(sim_debug_arena);
// Copy sim debug info
sim_debug_draw_descs_count = sim_output->debug_draw_descs_count;
sim_debug_draw_descs = PushStructsNoZero(sim_debug_arena, S_DebugDrawDesc, sim_debug_draw_descs_count);
CopyStructs(sim_debug_draw_descs, sim_output->debug_draw_descs, sim_debug_draw_descs_count);
}
// ////////////////////////////// // //////////////////////////////
// //- Update tiles from sim // //- Update tiles from sim
// { // {
// for (S_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next) // for (P_SnapshotNode *n = sim_output->first_snapshot_node; n; n = n->next)
// { // {
// S_Snapshot *snapshot = &n->snapshot; // P_Snapshot *snapshot = &n->snapshot;
// if (snapshot->tick > world->tick) // if (snapshot->tick > world->tick)
// { // {
// for (u64 placement_idx = 0; placement_idx < snapshot->tile_placements_count; ++placement_idx) // for (u64 placement_idx = 0; placement_idx < snapshot->tile_placements_count; ++placement_idx)
// { // {
// S_TilePlacement placement = snapshot->tile_placements[placement_idx]; // P_TilePlacement placement = snapshot->tile_placements[placement_idx];
// Rng2I32 dirty_rect = S_UpdateTilesInPlaceFromPlacement(tiles, placement); // Rng2I32 dirty_rect = P_UpdateTilesInPlaceFromPlacement(tiles, placement);
// G_CopyCpuToTexture( // G_CopyCpuToTexture(
// frame->cl, // frame->cl,
// gpu_tiles, VEC3I32(dirty_rect.p0.x, dirty_rect.p0.y, 0), // gpu_tiles, VEC3I32(dirty_rect.p0.x, dirty_rect.p0.y, 0),
@ -723,12 +710,12 @@ void V_TickForever(WaveLaneCtx *lane)
// if (sim_output->last_snapshot_node && sim_output->last_snapshot_node->snapshot.tick > world->tick) // if (sim_output->last_snapshot_node && sim_output->last_snapshot_node->snapshot.tick > world->tick)
// { // {
// ResetArena(world_arena); // ResetArena(world_arena);
// world = S_WorldFromSnapshot(world_arena, &sim_output->last_snapshot_node->snapshot); // world = P_WorldFromSnapshot(world_arena, &sim_output->last_snapshot_node->snapshot);
// V.lookup = S_LookupFromWorld(world_arena, world); // V.lookup = P_LookupFromWorld(world_arena, world);
// // Copy sim debug info // // Copy sim debug info
// sim_debug_draw_descs_count = sim_output->debug_draw_descs_count; // sim_debug_draw_descs_count = sim_output->debug_draw_descs_count;
// sim_debug_draw_descs = PushStructsNoZero(world_arena, S_DebugDrawDesc, sim_debug_draw_descs_count); // sim_debug_draw_descs = PushStructsNoZero(world_arena, P_DebugDrawDesc, sim_debug_draw_descs_count);
// CopyStructs(sim_debug_draw_descs, sim_output->debug_draw_descs, sim_debug_draw_descs_count); // CopyStructs(sim_debug_draw_descs, sim_output->debug_draw_descs, sim_debug_draw_descs_count);
// } // }
@ -860,8 +847,8 @@ void V_TickForever(WaveLaneCtx *lane)
Vec2 look_ratio = Zi; Vec2 look_ratio = Zi;
look_ratio.y = 0.25; look_ratio.y = 0.25;
look_ratio.x = look_ratio.y / (16.0 / 9.0); look_ratio.x = look_ratio.y / (16.0 / 9.0);
S_Ent *player = S_EntFromKey(world, V.player_key); P_Ent *player = P_EntFromKey(world, V.player_key);
target_camera_pos = S_WorldShapeFromEnt(player).centroid; target_camera_pos = P_WorldShapeFromEnt(player).centroid;
target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(player->look, look_ratio)); target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(player->look, look_ratio));
target_camera_zoom = 1; target_camera_zoom = 1;
} }
@ -929,7 +916,7 @@ void V_TickForever(WaveLaneCtx *lane)
frame->xf.cell_to_world = XformIdentity; frame->xf.cell_to_world = XformIdentity;
{ {
frame->xf.world_to_cell = ScaleXform(frame->xf.world_to_cell, VEC2(V_CellsPerMeter, V_CellsPerMeter)); frame->xf.world_to_cell = ScaleXform(frame->xf.world_to_cell, VEC2(V_CellsPerMeter, V_CellsPerMeter));
frame->xf.world_to_cell = TranslateXform(frame->xf.world_to_cell, VEC2((S_WorldPitch / 2.0), (S_WorldPitch / 2.0))); frame->xf.world_to_cell = TranslateXform(frame->xf.world_to_cell, VEC2((P_WorldPitch / 2.0), (P_WorldPitch / 2.0)));
frame->xf.cell_to_world = InvertXform(frame->xf.world_to_cell); frame->xf.cell_to_world = InvertXform(frame->xf.world_to_cell);
} }
@ -938,8 +925,8 @@ void V_TickForever(WaveLaneCtx *lane)
frame->xf.world_to_tile = XformIdentity; frame->xf.world_to_tile = XformIdentity;
frame->xf.tile_to_world = XformIdentity; frame->xf.tile_to_world = XformIdentity;
{ {
frame->xf.world_to_tile = ScaleXform(frame->xf.world_to_tile, VEC2(S_TilesPerMeter, S_TilesPerMeter)); frame->xf.world_to_tile = ScaleXform(frame->xf.world_to_tile, VEC2(P_TilesPerMeter, P_TilesPerMeter));
frame->xf.world_to_tile = TranslateXform(frame->xf.world_to_tile, VEC2((S_WorldPitch / 2.0), (S_WorldPitch / 2.0))); frame->xf.world_to_tile = TranslateXform(frame->xf.world_to_tile, VEC2((P_WorldPitch / 2.0), (P_WorldPitch / 2.0)));
frame->xf.tile_to_world = InvertXform(frame->xf.world_to_tile); frame->xf.tile_to_world = InvertXform(frame->xf.world_to_tile);
} }
@ -964,12 +951,12 @@ void V_TickForever(WaveLaneCtx *lane)
if (m1_held) if (m1_held)
{ {
frame->is_selecting = 1; frame->is_selecting = 1;
// frame->equipped_tile = S_TileKind_Floor; // frame->equipped_tile = P_TileKind_Floor;
} }
else if (m2_held) else if (m2_held)
{ {
frame->is_selecting = 1; frame->is_selecting = 1;
// frame->equipped_tile = S_TileKind_Empty; // frame->equipped_tile = P_TileKind_Empty;
} }
if (frame->is_selecting && last_frame->is_selecting) if (frame->is_selecting && last_frame->is_selecting)
@ -1003,8 +990,8 @@ void V_TickForever(WaveLaneCtx *lane)
tile_range.p0 = Vec2I32FromVec(FloorVec2(MulXformV2(frame->xf.world_to_tile, last_frame->world_selection.p0))); tile_range.p0 = Vec2I32FromVec(FloorVec2(MulXformV2(frame->xf.world_to_tile, last_frame->world_selection.p0)));
tile_range.p1 = Vec2I32FromVec(CeilVec2(MulXformV2(frame->xf.world_to_tile, last_frame->world_selection.p1))); tile_range.p1 = Vec2I32FromVec(CeilVec2(MulXformV2(frame->xf.world_to_tile, last_frame->world_selection.p1)));
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Delta); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
cmd->delta.kind = S_DeltaKind_Tile; cmd->delta.kind = P_DeltaKind_Tile;
cmd->delta.tile_kind = last_frame->equipped_tile; cmd->delta.tile_kind = last_frame->equipped_tile;
cmd->delta.tile_range = tile_range; cmd->delta.tile_range = tile_range;
} }
@ -1013,15 +1000,15 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Query entities //- Query entities
S_Ent *player = S_EntFromKey(world, V.player_key); P_Ent *player = P_EntFromKey(world, V.player_key);
S_Ent *hovered_ent = &S_NilEnt; P_Ent *hovered_ent = &P_NilEnt;
{ {
// TODO: Real world query // TODO: Real world query
S_Shape cursor_shape = S_ShapeFromDesc(.count = 1, .points = { frame->world_cursor }); P_Shape cursor_shape = P_ShapeFromDesc(.count = 1, .points = { frame->world_cursor });
for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent)) for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
{ {
S_Shape ent_shape = S_WorldShapeFromEnt(ent); P_Shape ent_shape = P_WorldShapeFromEnt(ent);
b32 is_hovered = S_CollisionResultFromShapes(ent_shape, cursor_shape).collision_points_count > 0; b32 is_hovered = P_CollisionResultFromShapes(ent_shape, cursor_shape).collision_points_count > 0;
if (is_hovered) if (is_hovered)
{ {
hovered_ent = ent; hovered_ent = ent;
@ -1551,9 +1538,9 @@ void V_TickForever(WaveLaneCtx *lane)
UI_Push(Tag, window->key.v); UI_Push(Tag, window->key.v);
if (window->is_tile_window) if (window->is_tile_window)
{ {
for (S_TileKind tile_kind = 0; tile_kind < S_TileKind_COUNT; ++tile_kind) for (P_TileKind tile_kind = 0; tile_kind < P_TileKind_COUNT; ++tile_kind)
{ {
String name = S_NameFromTileKind(tile_kind); String name = P_NameFromTileKind(tile_kind);
UI_Key key = UI_KeyF("Tile %F", FmtString(name)); UI_Key key = UI_KeyF("Tile %F", FmtString(name));
UI_BoxReport rep = UI_ReportsFromKey(key).draw; UI_BoxReport rep = UI_ReportsFromKey(key).draw;
@ -2232,13 +2219,13 @@ void V_TickForever(WaveLaneCtx *lane)
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
Vec2 tile_pos = MulXformV2(frame->xf.world_to_tile, frame->world_cursor); Vec2 tile_pos = MulXformV2(frame->xf.world_to_tile, frame->world_cursor);
Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor); Vec2 cell_pos = MulXformV2(frame->xf.world_to_cell, frame->world_cursor);
i32 tile_idx = S_TileIdxFromTilePos(tile_pos); i32 tile_idx = P_TileIdxFromTilePos(tile_pos);
UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos)); UI_BuildLabelF("Camera pos: %F", FmtFloat2(frame->camera_pos));
UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor)); UI_BuildLabelF("Cursor world pos: %F", FmtFloat2(frame->world_cursor));
UI_BuildLabelF("Cursor tile pos: %F", FmtFloat2(tile_pos)); UI_BuildLabelF("Cursor tile pos: %F", FmtFloat2(tile_pos));
UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx)); UI_BuildLabelF("Cursor tile idx: %F", FmtSint(tile_idx));
UI_BuildLabelF("Cursor cell pos: %F", FmtFloat2(cell_pos)); UI_BuildLabelF("Cursor cell pos: %F", FmtFloat2(cell_pos));
UI_BuildLabelF("Hovered ent: %F", S_FmtKey(hovered_ent->key)); UI_BuildLabelF("Hovered ent: %F", P_FmtKey(hovered_ent->key));
} }
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y); UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
{ {
@ -2511,8 +2498,8 @@ void V_TickForever(WaveLaneCtx *lane)
Vec2 player_pos = VEC2(5, 0); Vec2 player_pos = VEC2(5, 0);
if (kind == V_CmdKind_reset_world) if (kind == V_CmdKind_reset_world)
{ {
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Delta); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
cmd->delta.kind = S_DeltaKind_Reset; cmd->delta.kind = P_DeltaKind_Reset;
} }
else else
{ {
@ -2520,10 +2507,10 @@ void V_TickForever(WaveLaneCtx *lane)
} }
// Spawn player // Spawn player
{ {
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Delta); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
cmd->delta.kind = S_DeltaKind_RawEnt; cmd->delta.kind = P_DeltaKind_RawEnt;
S_Ent *ent = &cmd->delta.ent; P_Ent *ent = &cmd->delta.ent;
*ent = S_NilEnt; *ent = P_NilEnt;
ent->key = V.player_key; ent->key = V.player_key;
ent->xf = XformFromPos(player_pos); ent->xf = XformFromPos(player_pos);
ent->is_player = 1; ent->is_player = 1;
@ -2534,11 +2521,11 @@ void V_TickForever(WaveLaneCtx *lane)
case V_CmdKind_spawn_dummy: case V_CmdKind_spawn_dummy:
{ {
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Delta); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
cmd->delta.kind = S_DeltaKind_RawEnt; cmd->delta.kind = P_DeltaKind_RawEnt;
S_Ent *ent = &cmd->delta.ent; P_Ent *ent = &cmd->delta.ent;
*ent = S_NilEnt; *ent = P_NilEnt;
ent->key = S_RandKey(); ent->key = P_RandKey();
ent->xf = XformFromPos(frame->world_cursor); ent->xf = XformFromPos(frame->world_cursor);
ent->is_player = 1; ent->is_player = 1;
ent->has_weapon = 1; ent->has_weapon = 1;
@ -2549,9 +2536,9 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
if (hovered_ent->valid) if (hovered_ent->valid)
{ {
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Delta); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Delta);
cmd->delta.kind = S_DeltaKind_RawEnt; cmd->delta.kind = P_DeltaKind_RawEnt;
S_Ent *ent = &cmd->delta.ent; P_Ent *ent = &cmd->delta.ent;
ent->key = hovered_ent->key; ent->key = hovered_ent->key;
ent->exists = 0; ent->exists = 0;
} }
@ -2561,7 +2548,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
if (frame->is_editing) if (frame->is_editing)
{ {
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Save); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Save);
} }
} break; } break;
@ -2587,7 +2574,7 @@ void V_TickForever(WaveLaneCtx *lane)
f32 fire_presses = fire_held && !last_frame->held_buttons[Button_M1]; f32 fire_presses = fire_held && !last_frame->held_buttons[Button_M1];
Vec2 look = Zi; Vec2 look = Zi;
{ {
Vec2 center = S_WorldShapeFromEnt(player).centroid; Vec2 center = P_WorldShapeFromEnt(player).centroid;
look = SubVec2(frame->world_cursor, center); look = SubVec2(frame->world_cursor, center);
} }
if (frame->is_editing) if (frame->is_editing)
@ -2609,7 +2596,7 @@ void V_TickForever(WaveLaneCtx *lane)
// Push control cmd // Push control cmd
{ {
S_Cmd *cmd = V_PushSimCmd(S_CmdKind_Control); P_Cmd *cmd = V_PushSimCmd(P_CmdKind_Control);
cmd->target = V.player_key; cmd->target = V.player_key;
cmd->move = frame->move; cmd->move = frame->move;
cmd->look = frame->look; cmd->look = frame->look;
@ -2620,18 +2607,18 @@ void V_TickForever(WaveLaneCtx *lane)
////////////////////////////// //////////////////////////////
//- Submit sim commands //- Submit sim commands
LockTicketMutex(&S.input_back_tm); LockTicketMutex(&P.sim_input_back_tm);
{ {
S_InputState *v2s = &S.input_states[S.input_back_idx]; P_InputState *v2s = &P.sim_input_states[P.sim_input_back_idx];
for (S_CmdNode *src = frame->first_sim_cmd_node; src; src = src->next) for (P_CmdNode *src = frame->first_sim_cmd_node; src; src = src->next)
{ {
S_CmdNode *cmd_node = PushStruct(v2s->arena, S_CmdNode); P_CmdNode *cmd_node = PushStruct(v2s->arena, P_CmdNode);
cmd_node->cmd = src->cmd; cmd_node->cmd = src->cmd;
SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node); SllQueuePush(v2s->first_cmd_node, v2s->last_cmd_node, cmd_node);
++v2s->cmds_count; ++v2s->cmds_count;
} }
} }
UnlockTicketMutex(&S.input_back_tm); UnlockTicketMutex(&P.sim_input_back_tm);
@ -2648,7 +2635,7 @@ void V_TickForever(WaveLaneCtx *lane)
for (S_Ent *bullet = S_FirstEnt(world); bullet->valid; bullet = S_NextEnt(bullet)) for (P_Ent *bullet = P_FirstEnt(world); bullet->valid; bullet = P_NextEnt(bullet))
{ {
if (bullet->is_bullet) if (bullet->is_bullet)
{ {
@ -2828,7 +2815,7 @@ void V_TickForever(WaveLaneCtx *lane)
if (0) if (0)
{ {
for (S_Ent *bullet = S_FirstEnt(world); bullet->valid; bullet = S_NextEnt(bullet)) for (P_Ent *bullet = P_FirstEnt(world); bullet->valid; bullet = P_NextEnt(bullet))
{ {
if (bullet->is_bullet && bullet->has_hit) if (bullet->is_bullet && bullet->has_hit)
{ {
@ -2905,29 +2892,29 @@ void V_TickForever(WaveLaneCtx *lane)
// { // {
// for (S_Ent *firer = S_FirstEnt(world); firer->valid; firer = S_NextEnt(firer)) // for (P_Ent *firer = P_FirstEnt(world); firer->valid; firer = P_NextEnt(firer))
// { // {
// if (firer->fire_held) // if (firer->fire_held)
// { // {
// Xform firer_xf = firer->xf; // Xform firer_xf = firer->xf;
// S_Shape firer_world_shape = S_MulXformShape(firer_xf, firer->local_shape); // P_Shape firer_world_shape = P_MulXformShape(firer_xf, firer->local_shape);
// Vec2 ray_start = firer_world_shape.centroid; // Vec2 ray_start = firer_world_shape.centroid;
// Vec2 ray_dir = firer->look; // Vec2 ray_dir = firer->look;
// // TODO: Real raycast query // // TODO: Real raycast query
// S_Ent *closest_victim = &S_NilEnt; // P_Ent *closest_victim = &P_NilEnt;
// S_RaycastResult victim_raycast = Zi; // P_RaycastResult victim_raycast = Zi;
// { // {
// f32 closest_len_sq = Inf; // f32 closest_len_sq = Inf;
// for (S_Ent *victim = S_FirstEnt(world); victim->valid; victim = S_NextEnt(victim)) // for (P_Ent *victim = P_FirstEnt(world); victim->valid; victim = P_NextEnt(victim))
// { // {
// if (victim != firer) // if (victim != firer)
// { // {
// Xform victim_xf = victim->xf; // Xform victim_xf = victim->xf;
// S_Shape victim_world_shape = S_MulXformShape(victim_xf, victim->local_shape); // P_Shape victim_world_shape = P_MulXformShape(victim_xf, victim->local_shape);
// S_RaycastResult raycast = S_RaycastShape(victim_world_shape, ray_start, ray_dir); // P_RaycastResult raycast = P_RaycastShape(victim_world_shape, ray_start, ray_dir);
// if (raycast.is_intersecting) // if (raycast.is_intersecting)
// { // {
// f32 len_sq = Vec2LenSq(SubVec2(raycast.p, ray_start)); // f32 len_sq = Vec2LenSq(SubVec2(raycast.p, ray_start));
@ -2990,8 +2977,8 @@ void V_TickForever(WaveLaneCtx *lane)
// } // }
// // for (S_QueryResult query = S_FirstRaycast(wrold, ray_start, ray_dir); query. // // for (P_QueryResult query = P_FirstRaycast(wrold, ray_start, ray_dir); query.
// // S_RaycastWorldResult hits = S_RaycastWorld(world, ray_start, ray_dir) // // P_RaycastWorldResult hits = P_RaycastWorld(world, ray_start, ray_dir)
// // { // // {
// // } // // }
// } // }
@ -3027,14 +3014,98 @@ void V_TickForever(WaveLaneCtx *lane)
V_PushParticles(emitter); V_PushParticles(emitter);
} }
//////////////////////////////
//- Debug draw
{
// Copy debug draw data from sim
if (received_unseen_tick)
{
ResetArena(sim_debug_arena);
first_sim_debug_draw_node = 0;
last_sim_debug_draw_node = 0;
{
i64 dst_idx = 0;
P_DebugDrawNode *dst_nodes = PushStructsNoZero(sim_debug_arena, P_DebugDrawNode, sim_output->debug_draw_nodes_count);
for (P_DebugDrawNode *src = sim_output->first_debug_draw_node; src; src = src->next)
{
P_DebugDrawNode *dst = &dst_nodes[dst_idx];
*dst = *src;
dst_idx += 1;
SllQueuePush(first_sim_debug_draw_node, last_sim_debug_draw_node, dst);
}
}
}
// Merge vis debug draws with sim debug draws
P_DebugDrawNode *first_debug_draw_node = first_sim_debug_draw_node;
P_DebugDrawNode *last_debug_draw_node = last_sim_debug_draw_node;
if (P_tl.first_debug_draw_node)
{
if (last_debug_draw_node)
{
last_debug_draw_node->next = P_tl.first_debug_draw_node;
}
else
{
first_debug_draw_node = P_tl.first_debug_draw_node;
}
last_debug_draw_node = P_tl.last_debug_draw_node;
}
for (P_DebugDrawNode *n = first_debug_draw_node; n; n = n->next)
{
Vec4 color = Vec4FromU32(n->srgb32);
i32 detail = 24;
f32 radius = 5;
switch(n->kind)
{
case P_DebugDrawKind_Point:
{
Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, n->point.p);
V_DrawPoint(ui_p, color);
} break;
case P_DebugDrawKind_Line:
{
Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, n->line.p0);
Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, n->line.p1);
V_DrawLine(ui_p0, ui_p1, color);
} break;
case P_DebugDrawKind_Rect:
{
Rng2 ui_rect = Zi;
ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, n->rect.p0);
ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, n->rect.p1);
V_DrawRect(ui_rect, color, V_DrawFlag_Line);
} break;
case P_DebugDrawKind_Shape:
{
P_Shape ui_shape = P_MulXformShape(frame->xf.world_to_ui, n->shape);
V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
// V_DrawShape(ui_shape, color, detail, V_DrawFlag_None);
} break;
}
}
// Reset vis debug draws
ResetArena(P_tl.debug_arena);
P_tl.first_debug_draw_node = 0;
P_tl.last_debug_draw_node = 0;
P_tl.debug_draw_nodes_count = 0;
}
////////////////////////////// //////////////////////////////
//- Draw entities //- Draw entities
// for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent)) // for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
// { // {
// Xform ent_to_world_xf = ent->xf; // Xform ent_to_world_xf = ent->xf;
// Xform ent_to_draw_xf = MulXform(frame->xf.world_to_draw, ent_to_world_xf); // Xform ent_to_draw_xf = MulXform(frame->xf.world_to_draw, ent_to_world_xf);
// S_Shape draw_shape = S_MulXformShape(ent_to_draw_xf, ent->local_shape); // P_Shape draw_shape = P_MulXformShape(ent_to_draw_xf, ent->local_shape);
// f32 opacity = 0.5; // f32 opacity = 0.5;
@ -3056,7 +3127,7 @@ void V_TickForever(WaveLaneCtx *lane)
// // color.w *= opacity; // // color.w *= opacity;
// // f32 width = 0.1; // // f32 width = 0.1;
// // f32 height = 0.75; // // f32 height = 0.75;
// // S_Shape local_shape = S_ShapeFromDesc( // // P_Shape local_shape = P_ShapeFromDesc(
// // .count = 4, // // .count = 4,
// // .points = { // // .points = {
// // VEC2(-width / 2, -height), VEC2(width / 2, -height), // // VEC2(-width / 2, -height), VEC2(width / 2, -height),
@ -3065,7 +3136,7 @@ void V_TickForever(WaveLaneCtx *lane)
// // ); // // );
// // Xform local_xf = XformFromTrs(TRS(.t = { 0, 0 }, .r = Tau / 4)); // // Xform local_xf = XformFromTrs(TRS(.t = { 0, 0 }, .r = Tau / 4));
// // Xform xf = MulXform(ent_to_draw_xf, local_xf); // // Xform xf = MulXform(ent_to_draw_xf, local_xf);
// // S_Shape shape = S_MulXformShape(xf, local_shape); // // P_Shape shape = P_MulXformShape(xf, local_shape);
// // V_DrawShape(shape, color, 10, V_DrawFlag_Line); // // V_DrawShape(shape, color, 10, V_DrawFlag_Line);
// // } // // }
@ -3073,53 +3144,12 @@ void V_TickForever(WaveLaneCtx *lane)
// // { // // {
// // Vec4 color = Color_Orange; // // Vec4 color = Color_Orange;
// // color.w *= opacity; // // color.w *= opacity;
// // Rng2 bb = S_BoundingBoxFromShape(draw_shape); // // Rng2 bb = P_BoundingBoxFromShape(draw_shape);
// // V_DrawRect(bb, color, V_DrawFlag_Line); // // V_DrawRect(bb, color, V_DrawFlag_Line);
// // } // // }
// } // }
// } // }
//////////////////////////////
//- Draw sim debug shapes
for (u64 desc_idx = 0; desc_idx < sim_debug_draw_descs_count; ++desc_idx)
{
S_DebugDrawDesc *desc = &sim_debug_draw_descs[desc_idx];
Vec4 color = Vec4FromU32(desc->srgb32);
i32 detail = 24;
f32 radius = 5;
switch(desc->kind)
{
case S_DebugDrawKind_Point:
{
Vec2 ui_p = MulXformV2(frame->xf.world_to_ui, desc->point.p);
V_DrawPoint(ui_p, color);
} break;
case S_DebugDrawKind_Line:
{
Vec2 ui_p0 = MulXformV2(frame->xf.world_to_ui, desc->line.p0);
Vec2 ui_p1 = MulXformV2(frame->xf.world_to_ui, desc->line.p1);
V_DrawLine(ui_p0, ui_p1, color);
} break;
case S_DebugDrawKind_Rect:
{
Rng2 ui_rect = Zi;
ui_rect.p0 = MulXformV2(frame->xf.world_to_ui, desc->rect.p0);
ui_rect.p1 = MulXformV2(frame->xf.world_to_ui, desc->rect.p1);
V_DrawRect(ui_rect, color, V_DrawFlag_Line);
} break;
case S_DebugDrawKind_Shape:
{
S_Shape ui_shape = S_MulXformShape(frame->xf.world_to_ui, desc->shape);
V_DrawShape(ui_shape, color, detail, V_DrawFlag_Line);
// V_DrawShape(ui_shape, color, detail, V_DrawFlag_None);
} break;
}
}
////////////////////////////// //////////////////////////////
//- Render //- Render
@ -3207,9 +3237,9 @@ void V_TickForever(WaveLaneCtx *lane)
// Fill tile textures // Fill tile textures
{ {
for (S_TileKind tile_kind = 0; tile_kind < S_TileKind_COUNT; ++tile_kind) for (P_TileKind tile_kind = 0; tile_kind < P_TileKind_COUNT; ++tile_kind)
{ {
String tile_name = S_TileNameFromKind(tile_kind); String tile_name = P_TileNameFromKind(tile_kind);
String sheet_name = StringF(frame->arena, "tile/%F.ase", FmtString(tile_name)); String sheet_name = StringF(frame->arena, "tile/%F.ase", FmtString(tile_name));
ResourceKey sheet_resource = ResourceKeyFromStore(&P_Resources, sheet_name); ResourceKey sheet_resource = ResourceKeyFromStore(&P_Resources, sheet_name);
SPR_SheetKey sheet = SPR_SheetKeyFromResource(sheet_resource); SPR_SheetKey sheet = SPR_SheetKeyFromResource(sheet_resource);
@ -3343,8 +3373,8 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
i64 ents_to_prune_count = 0; i64 ents_to_prune_count = 0;
S_Ent **ents_to_prune = PushStructsNoZero(frame->arena, S_Ent *, world->ents_count); P_Ent **ents_to_prune = PushStructsNoZero(frame->arena, P_Ent *, world->ents_count);
for (S_Ent *ent = S_FirstEnt(world); ent->valid; ent = S_NextEnt(ent)) for (P_Ent *ent = P_FirstEnt(world); ent->valid; ent = P_NextEnt(ent))
{ {
if (ent->exists <= 0) if (ent->exists <= 0)
{ {
@ -3356,8 +3386,8 @@ void V_TickForever(WaveLaneCtx *lane)
for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx) for (i64 prune_idx = 0; prune_idx < ents_to_prune_count; ++prune_idx)
{ {
// FIXME: Add to free list // FIXME: Add to free list
S_Ent *ent = ents_to_prune[prune_idx]; P_Ent *ent = ents_to_prune[prune_idx];
S_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count]; P_EntBin *bin = &world->ent_bins[ent->key.v % world->ent_bins_count];
DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin); DllQueueRemoveNP(bin->first, bin->last, ent, next_in_bin, prev_in_bin);
DllQueueRemove(world->first_ent, world->last_ent, ent); DllQueueRemove(world->first_ent, world->last_ent, ent);
world->ents_count -= 1; world->ents_count -= 1;

View File

@ -234,7 +234,7 @@ Struct(V_Frame)
// Editor state // Editor state
V_EditMode edit_mode; V_EditMode edit_mode;
S_TileKind equipped_tile; P_TileKind equipped_tile;
// Editor // Editor
b32 is_selecting; b32 is_selecting;
@ -273,8 +273,8 @@ Struct(V_Frame)
// Sim cmds // Sim cmds
u64 sim_cmds_count; u64 sim_cmds_count;
S_CmdNode *first_sim_cmd_node; P_CmdNode *first_sim_cmd_node;
S_CmdNode *last_sim_cmd_node; P_CmdNode *last_sim_cmd_node;
// Emitters // Emitters
i64 emitters_count; i64 emitters_count;
@ -284,7 +284,7 @@ Struct(V_Frame)
Struct(V_Ctx) Struct(V_Ctx)
{ {
S_Key player_key; P_Key player_key;
i64 panels_count; i64 panels_count;
i64 windows_count; i64 windows_count;
@ -315,7 +315,7 @@ void V_Shutdown(void);
V_Frame *V_CurrentFrame(void); V_Frame *V_CurrentFrame(void);
V_Frame *V_LastFrame(void); V_Frame *V_LastFrame(void);
V_Cmd *V_PushVisCmd(String name); V_Cmd *V_PushVisCmd(String name);
S_Cmd *V_PushSimCmd(S_CmdKind kind); P_Cmd *V_PushSimCmd(P_CmdKind kind);
String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey); String V_StringFromHotkey(Arena *arena, V_Hotkey hotkey);
void V_PushParticles(V_Emitter src); void V_PushParticles(V_Emitter src);
@ -323,7 +323,7 @@ void V_PushParticles(V_Emitter src);
//~ Draw helpers //~ Draw helpers
void V_DrawPoly(Vec2Array points, Vec4 srgb, V_DrawFlag flags); void V_DrawPoly(Vec2Array points, Vec4 srgb, V_DrawFlag flags);
void V_DrawShape(S_Shape shape, Vec4 srgb, i32 detail, V_DrawFlag flags); void V_DrawShape(P_Shape shape, Vec4 srgb, i32 detail, V_DrawFlag flags);
void V_DrawLine(Vec2 p0, Vec2 p1, Vec4 srgb); void V_DrawLine(Vec2 p0, Vec2 p1, Vec4 srgb);
void V_DrawRect(Rng2 rect, Vec4 srgb, V_DrawFlag flags); void V_DrawRect(Rng2 rect, Vec4 srgb, V_DrawFlag flags);
void V_DrawPoint(Vec2 p, Vec4 srgb); void V_DrawPoint(Vec2 p, Vec4 srgb);

View File

@ -69,7 +69,7 @@ ComputeShader2D(V_BackdropCS, 8, 8)
{ {
V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0]; V_GpuParams params = G_Dereference<V_GpuParams>(V_ShaderConst_Params)[0];
RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw); RWTexture2D<Vec4> target = G_Dereference<Vec4>(params.target_rw);
Texture2D<S_TileKind> tiles = G_Dereference<S_TileKind>(params.tiles); Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles);
const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)); const Vec4 background_color_a = LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1));
const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)); const Vec4 background_color_b = LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1));
@ -82,10 +82,10 @@ ComputeShader2D(V_BackdropCS, 8, 8)
Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1))); Vec2 cell_pos = floor(mul(params.xf.world_to_cell, Vec3(world_pos, 1)));
Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1));
S_TileKind tile = tiles.Load(Vec3(tile_pos, 0)); P_TileKind tile = tiles.Load(Vec3(tile_pos, 0));
f32 half_thickness = 1; f32 half_thickness = 1;
f32 half_bounds_size = S_WorldPitch * 0.5; f32 half_bounds_size = P_WorldPitch * 0.5;
Vec2 bounds_screen_p0 = mul(params.xf.world_to_ui, Vec3(-half_bounds_size, -half_bounds_size, 1)); Vec2 bounds_screen_p0 = mul(params.xf.world_to_ui, Vec3(-half_bounds_size, -half_bounds_size, 1));
Vec2 bounds_screen_p1 = mul(params.xf.world_to_ui, Vec3(half_bounds_size, half_bounds_size, 1)); Vec2 bounds_screen_p1 = mul(params.xf.world_to_ui, Vec3(half_bounds_size, half_bounds_size, 1));
bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) && bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) &&
@ -125,17 +125,17 @@ ComputeShader2D(V_BackdropCS, 8, 8)
// Tile test // Tile test
// TODO: Remove this // TODO: Remove this
{ {
S_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0)); P_TileKind tile_tl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y - 1, 0));
S_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0)); P_TileKind tile_tr = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y - 1, 0));
S_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0)); P_TileKind tile_br = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y + 1, 0));
S_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0)); P_TileKind tile_bl = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y + 1, 0));
S_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0)); P_TileKind tile_t = tiles.Load(Vec3(tile_pos.x, tile_pos.y - 1, 0));
S_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0)); P_TileKind tile_r = tiles.Load(Vec3(tile_pos.x + 1, tile_pos.y, 0));
S_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0)); P_TileKind tile_b = tiles.Load(Vec3(tile_pos.x, tile_pos.y + 1, 0));
S_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0)); P_TileKind tile_l = tiles.Load(Vec3(tile_pos.x - 1, tile_pos.y, 0));
f32 tile_edge_dist = Inf; f32 tile_edge_dist = Inf;
S_TileKind edge_tile = tile; P_TileKind edge_tile = tile;
if (tile_tl != tile) { edge_tile = tile_tl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), floor(tile_pos.y)))); } if (tile_tl != tile) { edge_tile = tile_tl; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(floor(tile_pos.x), floor(tile_pos.y)))); }
if (tile_tr != tile) { edge_tile = tile_tr; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), floor(tile_pos.y)))); } if (tile_tr != tile) { edge_tile = tile_tr; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), floor(tile_pos.y)))); }
if (tile_br != tile) { edge_tile = tile_br; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), ceil(tile_pos.y)))); } if (tile_br != tile) { edge_tile = tile_br; tile_edge_dist = min(tile_edge_dist, length(tile_pos - Vec2(ceil(tile_pos.x), ceil(tile_pos.y)))); }
@ -145,14 +145,14 @@ ComputeShader2D(V_BackdropCS, 8, 8)
if (tile_t != tile) { edge_tile = tile_t; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.y)); } if (tile_t != tile) { edge_tile = tile_t; tile_edge_dist = min(tile_edge_dist, frac(tile_pos.y)); }
if (tile_b != tile) { edge_tile = tile_b; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.y)); } if (tile_b != tile) { edge_tile = tile_b; tile_edge_dist = min(tile_edge_dist, 1.0 - frac(tile_pos.y)); }
if (tile == S_TileKind_Wall) if (tile == P_TileKind_Wall)
{ {
Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1)); Vec4 outer = LinearFromSrgb(Vec4(0.05, 0.05, 0.05, 1));
Vec4 inner = LinearFromSrgb(Vec4(0.10, 0.10, 0.10, 1)); Vec4 inner = LinearFromSrgb(Vec4(0.10, 0.10, 0.10, 1));
result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375)); result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.375));
// result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.5)); // result = lerp(outer, inner, smoothstep(0, 1, tile_edge_dist / 0.5));
} }
else if (tile != S_TileKind_Empty) else if (tile != P_TileKind_Empty)
{ {
SamplerState wrap_sampler = G_Dereference(params.pt_wrap_sampler); SamplerState wrap_sampler = G_Dereference(params.pt_wrap_sampler);
SPR_Slice slice = params.tile_slices[tile]; SPR_Slice slice = params.tile_slices[tile];
@ -166,12 +166,12 @@ ComputeShader2D(V_BackdropCS, 8, 8)
// { // {
// default: break; // default: break;
// case S_TileKind_Floor: // case P_TileKind_Floor:
// { // {
// result = Color_Blue; // result = Color_Blue;
// } break; // } break;
// case S_TileKind_Wall: // case P_TileKind_Wall:
// { // {
// // result = Color_Red; // // result = Color_Red;
// result = Color_Black; // result = Color_Black;
@ -517,10 +517,10 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
Vec2 world_pos = mul(params.xf.ui_to_world, Vec3(ui_pos, 1)); Vec2 world_pos = mul(params.xf.ui_to_world, Vec3(ui_pos, 1));
Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1)); Vec2 tile_pos = mul(params.xf.world_to_tile, Vec3(world_pos, 1));
S_TileKind equipped_tile = params.equipped_tile; P_TileKind equipped_tile = params.equipped_tile;
f32 half_thickness = 1; f32 half_thickness = 1;
f32 half_bounds_size = S_WorldPitch * 0.5; f32 half_bounds_size = P_WorldPitch * 0.5;
Vec2 bounds_screen_p0 = mul(params.xf.world_to_ui, Vec3(-half_bounds_size, -half_bounds_size, 1)); Vec2 bounds_screen_p0 = mul(params.xf.world_to_ui, Vec3(-half_bounds_size, -half_bounds_size, 1));
Vec2 bounds_screen_p1 = mul(params.xf.world_to_ui, Vec3(half_bounds_size, half_bounds_size, 1)); Vec2 bounds_screen_p1 = mul(params.xf.world_to_ui, Vec3(half_bounds_size, half_bounds_size, 1));
bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) && bool is_in_bounds = ui_pos.x > (bounds_screen_p0.x - half_thickness) &&
@ -558,10 +558,10 @@ PixelShader(V_OverlayPS, V_OverlayPSOutput, V_OverlayPSInput input)
// else // else
{ {
if ( if (
world_pos.x > -(S_WorldPitch / 2) && world_pos.x > -(P_WorldPitch / 2) &&
world_pos.y > -(S_WorldPitch / 2) && world_pos.y > -(P_WorldPitch / 2) &&
world_pos.x < (S_WorldPitch / 2) && world_pos.x < (P_WorldPitch / 2) &&
world_pos.y < (S_WorldPitch / 2) && world_pos.y < (P_WorldPitch / 2) &&
tile_pos.x >= tile_selection.p0.x && tile_pos.x >= tile_selection.p0.x &&
tile_pos.x <= tile_selection.p1.x && tile_pos.x <= tile_selection.p1.x &&
tile_pos.y >= tile_selection.p0.y && tile_pos.y >= tile_selection.p0.y &&

View File

@ -71,7 +71,7 @@ Struct(V_GpuParams)
G_SamplerStateRef pt_wrap_sampler; G_SamplerStateRef pt_wrap_sampler;
V_SelectionMode selection_mode; V_SelectionMode selection_mode;
S_TileKind equipped_tile; P_TileKind equipped_tile;
b32 has_mouse_focus; b32 has_mouse_focus;
b32 has_keyboard_focus; b32 has_keyboard_focus;
@ -99,7 +99,7 @@ Struct(V_GpuParams)
G_RWTexture2DRef stains; G_RWTexture2DRef stains;
G_RWTexture2DRef drynesses; G_RWTexture2DRef drynesses;
SPR_Slice tile_slices[S_TileKind_COUNT]; SPR_Slice tile_slices[P_TileKind_COUNT];
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -92,6 +92,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet, String slice_name)
SPR_CmdNode *n = SPR.submit.first_free; SPR_CmdNode *n = SPR.submit.first_free;
if (n) if (n)
{ {
SllStackPop(SPR.submit.first_free);
ZeroStruct(n); ZeroStruct(n);
} }
else else