tron@2186: /* $Id$ */ tron@2186: darkvater@406: #ifndef SPRITE_H darkvater@406: #define SPRITE_H darkvater@406: darkvater@406: darkvater@406: /* The following describes bunch of sprites to be drawn together in a single 3D darkvater@406: * bounding box. Used especially for various multi-sprite buildings (like darkvater@406: * depots or stations): */ darkvater@406: darkvater@406: typedef struct DrawTileSeqStruct { darkvater@408: int8 delta_x; // 0x80 is sequence terminator darkvater@406: int8 delta_y; darkvater@406: int8 delta_z; darkvater@406: byte width,height; darkvater@406: byte unk; // 'depth', just z-size; TODO: rename darkvater@406: uint32 image; darkvater@406: } DrawTileSeqStruct; darkvater@406: darkvater@406: typedef struct DrawTileSprites { darkvater@406: SpriteID ground_sprite; darkvater@406: DrawTileSeqStruct const *seq; darkvater@406: } DrawTileSprites; darkvater@406: darkvater@408: // Iterate through all DrawTileSeqStructs in DrawTileSprites. darkvater@406: #define foreach_draw_tile_seq(idx, list) for (idx = list; ((byte) idx->delta_x) != 0x80; idx++) darkvater@406: darkvater@406: darkvater@406: /* This is for custom sprites: */ darkvater@406: darkvater@408: tron@1477: typedef struct SpriteGroup SpriteGroup; darkvater@408: tron@1477: typedef struct RealSpriteGroup { darkvater@406: // XXX: Would anyone ever need more than 16 spritesets? Maybe we should darkvater@406: // use even less, now we take whole 8kb for custom sprites table, oh my! darkvater@406: byte sprites_per_set; // means number of directions - 4 or 8 darkvater@406: darkvater@406: // Loaded = in motion, loading = not moving darkvater@406: // Each group contains several spritesets, for various loading stages darkvater@406: darkvater@406: // XXX: For stations the meaning is different - loaded is for stations darkvater@406: // with small amount of cargo whilst loading is for stations with a lot darkvater@406: // of da stuff. darkvater@406: darkvater@406: byte loaded_count; darkvater@406: uint16 loaded[16]; // sprite ids darkvater@406: byte loading_count; darkvater@406: uint16 loading[16]; // sprite ids tron@1477: } RealSpriteGroup; darkvater@406: darkvater@408: /* Shared by deterministic and random groups. */ tron@1477: typedef enum VarSpriteGroupScope { darkvater@408: VSG_SCOPE_SELF, darkvater@408: // Engine of consists for vehicles, city for stations. darkvater@408: VSG_SCOPE_PARENT, tron@1477: } VarSpriteGroupScope; darkvater@408: tron@1477: typedef struct DeterministicSpriteGroupRanges DeterministicSpriteGroupRanges; darkvater@408: tron@1477: typedef enum DeterministicSpriteGroupOperation { tron@1477: DSG_OP_NONE, tron@1477: DSG_OP_DIV, tron@1477: DSG_OP_MOD, tron@1477: } DeterministicSpriteGroupOperation; tron@1477: tron@1477: typedef struct DeterministicSpriteGroupRange DeterministicSpriteGroupRange; tron@1477: tron@1477: typedef struct DeterministicSpriteGroup { darkvater@408: // Take this variable: tron@1477: VarSpriteGroupScope var_scope; darkvater@408: byte variable; darkvater@408: darkvater@408: // Do this with it: darkvater@408: byte shift_num; darkvater@408: byte and_mask; darkvater@408: darkvater@408: // Then do this with it: tron@1477: DeterministicSpriteGroupOperation operation; darkvater@408: byte add_val; darkvater@408: byte divmod_val; tron@915: darkvater@408: // And apply it to this: darkvater@408: byte num_ranges; tron@1477: DeterministicSpriteGroupRange *ranges; // Dynamically allocated darkvater@408: darkvater@408: // Dynamically allocated, this is the sole owner tron@1477: SpriteGroup *default_group; tron@1477: } DeterministicSpriteGroup; darkvater@408: tron@1477: typedef enum RandomizedSpriteGroupCompareMode { tron@1477: RSG_CMP_ANY, tron@1477: RSG_CMP_ALL, tron@1477: } RandomizedSpriteGroupCompareMode; tron@1477: tron@1477: typedef struct RandomizedSpriteGroup { tron@445: // Take this object: tron@1477: VarSpriteGroupScope var_scope; tron@445: tron@445: // Check for these triggers: tron@1477: RandomizedSpriteGroupCompareMode cmp_mode; tron@445: byte triggers; tron@445: tron@445: // Look for this in the per-object randomized bitmask: tron@445: byte lowest_randbit; tron@445: byte num_groups; // must be power of 2 tron@445: tron@445: // Take the group with appropriate index: tron@1477: SpriteGroup *groups; tron@1477: } RandomizedSpriteGroup; tron@1477: hackykid@1883: typedef struct CallbackResultSpriteGroup { hackykid@1883: uint16 result; hackykid@1883: } CallbackResultSpriteGroup; hackykid@1883: tron@1477: typedef enum SpriteGroupType { tron@1477: SGT_REAL, tron@1477: SGT_DETERMINISTIC, tron@1477: SGT_RANDOMIZED, hackykid@1883: SGT_CALLBACK, tron@1477: } SpriteGroupType; tron@445: darkvater@408: struct SpriteGroup { tron@1477: SpriteGroupType type; darkvater@408: darkvater@408: union { tron@1477: RealSpriteGroup real; tron@1477: DeterministicSpriteGroup determ; tron@1477: RandomizedSpriteGroup random; hackykid@1883: CallbackResultSpriteGroup callback; darkvater@408: } g; darkvater@408: }; darkvater@408: darkvater@413: struct DeterministicSpriteGroupRange { tron@1477: SpriteGroup group; darkvater@413: byte low; darkvater@413: byte high; darkvater@408: }; darkvater@408: darkvater@413: /* This takes value (probably of the variable specified in the group) and darkvater@413: * chooses corresponding SpriteGroup accordingly to the given darkvater@413: * DeterministicSpriteGroup. */ darkvater@413: struct SpriteGroup *EvalDeterministicSpriteGroup(struct DeterministicSpriteGroup *dsg, int value); darkvater@413: /* Get value of a common deterministic SpriteGroup variable. */ darkvater@413: int GetDeterministicSpriteValue(byte var); darkvater@408: tron@445: /* This takes randomized bitmask (probably associated with tron@445: * vehicle/station/whatever) and chooses corresponding SpriteGroup tron@445: * accordingly to the given RandomizedSpriteGroup. */ tron@1477: SpriteGroup *EvalRandomizedSpriteGroup(RandomizedSpriteGroup *rsg, byte random_bits); tron@445: /* Triggers given RandomizedSpriteGroup with given bitmask and returns and-mask tron@445: * of random bits to be reseeded, or zero if there were no triggers matched tron@445: * (then they are |ed to @waiting_triggers instead). */ tron@1477: byte RandomizedSpriteGroupTriggeredBits(RandomizedSpriteGroup *rsg, byte triggers, byte *waiting_triggers); tron@445: darkvater@406: #endif