changeset 15974:cd560759db07 draft

(svn r20662) -Codechange: implement object animation
author rubidium <rubidium@openttd.org>
date Sat, 28 Aug 2010 18:51:47 +0000
parents d8e7acae5264
children abda7bdf71bc
files src/landscape.cpp src/newgrf_callbacks.h src/newgrf_object.cpp src/newgrf_object.h src/object_cmd.cpp
diffstat 5 files changed, 84 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/landscape.cpp
+++ b/src/landscape.cpp
@@ -952,6 +952,7 @@
 	if (_settings_game.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest();
 }
 
+void OnTick_Objects();
 void OnTick_Town();
 void OnTick_Trees();
 void OnTick_Station();
@@ -966,5 +967,6 @@
 	OnTick_Station();
 	OnTick_Industry();
 
+	OnTick_Objects();
 	OnTick_Companies();
 }
--- a/src/newgrf_callbacks.h
+++ b/src/newgrf_callbacks.h
@@ -256,13 +256,13 @@
 	CBID_OBJECT_LAND_SLOPE_CHECK         = 0x157, // 15 bit callback, not implemented
 
 	/** Determine the next animation frame for a house. */
-	CBID_OBJECT_ANIMATION_NEXT_FRAME     = 0x158, // 15 bit callback, not implemented
+	CBID_OBJECT_ANIMATION_NEXT_FRAME     = 0x158, // 15 bit callback
 
 	/** Called for periodically starting or stopping the animation. */
-	CBID_OBJECT_ANIMATION_START_STOP     = 0x159, // 15 bit callback, not implemented
+	CBID_OBJECT_ANIMATION_START_STOP     = 0x159, // 15 bit callback
 
 	/** Called to indicate how long the current animation frame should last. */
-	CBID_OBJECT_ANIMATION_SPEED          = 0x15A, // 8 bit callback, not implemented
+	CBID_OBJECT_ANIMATION_SPEED          = 0x15A, // 8 bit callback
 
 	/** Called to determine the colour of a town building. */
 	CBID_OBJECT_COLOUR                   = 0x15B, // 15 bit callback
--- a/src/newgrf_object.cpp
+++ b/src/newgrf_object.cpp
@@ -13,12 +13,11 @@
 #include "company_base.h"
 #include "company_func.h"
 #include "core/mem_func.hpp"
-#include "date_func.h"
 #include "debug.h"
-#include "landscape.h"
 #include "newgrf.h"
 #include "newgrf_class_func.h"
 #include "newgrf_object.h"
+#include "newgrf_sound.h"
 #include "newgrf_spritegroup.h"
 #include "newgrf_town.h"
 #include "object_base.h"
@@ -27,6 +26,7 @@
 #include "town.h"
 #include "viewport_func.h"
 #include "water.h"
+#include "newgrf_animation_base.h"
 
 /** The override manager for our objects. */
 ObjectOverrideManager _object_mngr(NEW_OBJECT_OFFSET, NUM_OBJECTS, INVALID_OBJECT_TYPE);
@@ -475,3 +475,53 @@
 
 	DrawNewGRFTileSeqInGUI(x, y, dts, 0, palette);
 }
+
+/** Helper class for animation control. */
+struct ObjectAnimationBase : public AnimationBase<ObjectAnimationBase, ObjectSpec, Object, GetObjectCallback> {
+	static const CallbackID cb_animation_speed      = CBID_OBJECT_ANIMATION_SPEED;
+	static const CallbackID cb_animation_next_frame = CBID_OBJECT_ANIMATION_NEXT_FRAME;
+
+	static const ObjectCallbackMask cbm_animation_speed      = CBM_OBJ_ANIMATION_SPEED;
+	static const ObjectCallbackMask cbm_animation_next_frame = CBM_OBJ_ANIMATION_NEXT_FRAME;
+};
+
+/**
+ * Handle the animation of the object tile.
+ * @param tile The tile to animate.
+ */
+void AnimateNewObjectTile(TileIndex tile)
+{
+	const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
+	if (spec == NULL || !(spec->flags & OBJECT_FLAG_ANIMATION)) return;
+
+	ObjectAnimationBase::AnimateTile(spec, Object::GetByTile(tile), tile, (spec->flags & OBJECT_FLAG_ANIM_RANDOM_BITS) != 0);
+}
+
+/**
+ * Trigger the update of animation on a single tile.
+ * @param o       The object that got triggered.
+ * @param tile    The location of the triggered tile.
+ * @param trigger The trigger that is triggered.
+ * @param spec    The spec associated with the object.
+ */
+void TriggerObjectTileAnimation(const Object *o, TileIndex tile, ObjectAnimationTrigger trigger, const ObjectSpec *spec)
+{
+	if (!HasBit(spec->animation.triggers, trigger)) return;
+
+	ObjectAnimationBase::ChangeAnimationFrame(CBID_OBJECT_ANIMATION_START_STOP, spec, o, tile, Random(), trigger);
+}
+
+/**
+ * Trigger the update of animation on a whole object.
+ * @param o       The object that got triggered.
+ * @param trigger The trigger that is triggered.
+ * @param spec    The spec associated with the object.
+ */
+void TriggerObjectAnimation(const Object *o, ObjectAnimationTrigger trigger, const ObjectSpec *spec)
+{
+	if (!HasBit(spec->animation.triggers, trigger)) return;
+
+	TILE_AREA_LOOP(tile, o->location) {
+		TriggerObjectTileAnimation(o, tile, trigger, spec);
+	}
+}
--- a/src/newgrf_object.h
+++ b/src/newgrf_object.h
@@ -120,5 +120,8 @@
 
 void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec);
 void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec);
+void AnimateNewObjectTile(TileIndex tile);
+void TriggerObjectTileAnimation(const Object *o, TileIndex tile, ObjectAnimationTrigger trigger, const ObjectSpec *spec);
+void TriggerObjectAnimation(const Object *o, ObjectAnimationTrigger trigger, const ObjectSpec *spec);
 
 #endif /* NEWGRF_OBJECT_H */
--- a/src/object_cmd.cpp
+++ b/src/object_cmd.cpp
@@ -89,6 +89,7 @@
 	}
 
 	Object::IncTypeCount(type);
+	if (spec->flags & OBJECT_FLAG_ANIMATION) TriggerObjectAnimation(o, OAT_BUILT, spec);
 }
 
 /**
@@ -379,6 +380,9 @@
 
 static void TileLoop_Object(TileIndex tile)
 {
+	const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
+	if (spec->flags & OBJECT_FLAG_ANIMATION) TriggerObjectTileAnimation(Object::GetByTile(tile), tile, OAT_TILELOOP, spec);
+
 	if (IsTileOnWater(tile)) TileLoop_Water(tile);
 
 	if (!IsCompanyHQ(tile)) return;
@@ -424,6 +428,25 @@
 	return true;
 }
 
+static void AnimateTile_Object(TileIndex tile)
+{
+	AnimateNewObjectTile(tile);
+}
+
+/** Call the ticks on the objects. */
+void OnTick_Objects()
+{
+	const Object *o;
+	FOR_ALL_OBJECTS(o) {
+		/* Run 250 tick interval trigger for object animation.
+		 * Object index is included so that triggers are not all done
+		 * at the same time. */
+		if ((_tick_counter + o->index) % 250 == 0) {
+			const ObjectSpec *spec = ObjectSpec::GetByTile(o->location.tile);
+			if (spec->flags & OBJECT_FLAG_ANIMATION) TriggerObjectAnimation(o, OAT_250_TICKS, spec);
+		}
+	}
+}
 
 /* checks, if a radio tower is within a 9x9 tile square around tile */
 static bool IsRadioTowerNearby(TileIndex tile)
@@ -564,7 +587,7 @@
 	GetTileDesc_Object,          // get_tile_desc_proc
 	GetTileTrackStatus_Object,   // get_tile_track_status_proc
 	ClickTile_Object,            // click_tile_proc
-	NULL,                        // animate_tile_proc
+	AnimateTile_Object,          // animate_tile_proc
 	TileLoop_Object,             // tile_loop_clear
 	ChangeTileOwner_Object,      // change_tile_owner_clear
 	NULL,                        // add_produced_cargo_proc