Forráskód Böngészése

Add RenderWorld.sprite_flip_x/y()

Daniele Bartolini 9 éve
szülő
commit
ddda368046

+ 12 - 0
docs/lua_api.rst

@@ -617,6 +617,18 @@ Sprite
 **sprite_destroy** (rw, id)
 	Destroys the sprite *id*.
 
+**sprite_set_frame** (rw, id, frame)
+	Sets the frame *index* of the sprite *id*.
+
+**sprite_set_visible** (rw, id, visible)
+	Sets whether the sprite *id* is *visible*.
+
+**sprite_flip_x** (rw, id, flip)
+	Sets whether to flip the sprite on the y-axis.
+
+**sprite_flip_y** (rw, id, flip)
+	Sets whether to flip the sprite on the y-axis.
+
 **sprite_instances** (rw, unit) : Id
 	Returns the IDs for all the sprites of the *unit*.
 

+ 16 - 0
src/lua/lua_api.cpp

@@ -1923,6 +1923,20 @@ static int render_world_sprite_set_frame(lua_State* L)
 	return 0;
 }
 
+static int render_world_sprite_flip_x(lua_State* L)
+{
+	LuaStack stack(L);
+	stack.get_render_world(1)->sprite_flip_x(stack.get_sprite_instance(2), stack.get_bool(3));
+	return 0;
+}
+
+static int render_world_sprite_flip_y(lua_State* L)
+{
+	LuaStack stack(L);
+	stack.get_render_world(1)->sprite_flip_y(stack.get_sprite_instance(2), stack.get_bool(3));
+	return 0;
+}
+
 static int render_world_sprite_raycast(lua_State* L)
 {
 	LuaStack stack(L);
@@ -3374,6 +3388,8 @@ void load_api(LuaEnvironment& env)
 	env.add_module_function("RenderWorld", "sprite_instances",     render_world_sprite_instances);
 	env.add_module_function("RenderWorld", "sprite_set_frame",     render_world_sprite_set_frame);
 	env.add_module_function("RenderWorld", "sprite_set_visible",   render_world_sprite_set_visible);
+	env.add_module_function("RenderWorld", "sprite_flip_x",        render_world_sprite_flip_x);
+	env.add_module_function("RenderWorld", "sprite_flip_y",        render_world_sprite_flip_y);
 	env.add_module_function("RenderWorld", "sprite_raycast",       render_world_sprite_raycast);
 	env.add_module_function("RenderWorld", "light_create",         render_world_light_create);
 	env.add_module_function("RenderWorld", "light_destroy",        render_world_light_destroy);

+ 19 - 11
src/resource/sprite_resource.cpp

@@ -78,17 +78,25 @@ namespace sprite_resource_internal
 			x1 /= CROWN_DEFAULT_PIXELS_PER_METER;
 			y1 /= CROWN_DEFAULT_PIXELS_PER_METER;
 
-			array::push_back(vertices, x0); array::push_back(vertices, y0); // position
-			array::push_back(vertices, u0); array::push_back(vertices, v0); // uv
-
-			array::push_back(vertices, x1); array::push_back(vertices, y0); // position
-			array::push_back(vertices, u1); array::push_back(vertices, v0); // uv
-
-			array::push_back(vertices, x1); array::push_back(vertices, y1); // position
-			array::push_back(vertices, u1); array::push_back(vertices, v1); // uv
-
-			array::push_back(vertices, x0); array::push_back(vertices, y1); // position
-			array::push_back(vertices, u0); array::push_back(vertices, v1); // uv
+			array::push_back(vertices, x0);
+			array::push_back(vertices, y0);
+			array::push_back(vertices, u0);
+			array::push_back(vertices, v0);
+
+			array::push_back(vertices, x1);
+			array::push_back(vertices, y0);
+			array::push_back(vertices, u1);
+			array::push_back(vertices, v0);
+
+			array::push_back(vertices, x1);
+			array::push_back(vertices, y1);
+			array::push_back(vertices, u1);
+			array::push_back(vertices, v1);
+
+			array::push_back(vertices, x0);
+			array::push_back(vertices, y1);
+			array::push_back(vertices, u0);
+			array::push_back(vertices, v1);
 		}
 
 		const u32 num_vertices = array::size(vertices) / 4; // 4 components per vertex

+ 73 - 5
src/world/render_world.cpp

@@ -152,17 +152,30 @@ void RenderWorld::sprite_set_material(SpriteInstance i, StringId64 id)
 	_sprite_manager._data.material[i.i] = id;
 }
 
+void RenderWorld::sprite_set_frame(SpriteInstance i, u32 index)
+{
+	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
+	_sprite_manager._data.frame[i.i] = index;
+}
+
 void RenderWorld::sprite_set_visible(SpriteInstance i, bool visible)
 {
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
 }
 
-void RenderWorld::sprite_set_frame(SpriteInstance i, u32 index)
+void RenderWorld::sprite_flip_x(SpriteInstance i, bool flip)
 {
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
-	_sprite_manager._data.frame[i.i] = index;
+	_sprite_manager._data.flip_x[i.i] = flip;
+}
+
+void RenderWorld::sprite_flip_y(SpriteInstance i, bool flip)
+{
+	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
+	_sprite_manager._data.flip_y[i.i] = flip;
 }
 
+
 f32 RenderWorld::sprite_raycast(SpriteInstance i, const Vector3& from, const Vector3& dir)
 {
 	CE_ASSERT(i.i < _sprite_manager._data.size, "Index out of bounds");
@@ -347,8 +360,53 @@ void RenderWorld::render(const Matrix4x4& view, const Matrix4x4& projection)
 		{
 			const f32* frame = sprite_resource::frame_data(sid.resource[i], sid.frame[i]);
 
-			for (u32 vi = 0; vi < 16; ++vi)
-				*vdata++ = *frame++;
+			float u0 = frame[ 2]; // u
+			float v0 = frame[ 3]; // v
+
+			float u1 = frame[ 6]; // u
+			float v1 = frame[ 7]; // v
+
+			float u2 = frame[10]; // u
+			float v2 = frame[11]; // v
+
+			float u3 = frame[14]; // u
+			float v3 = frame[15]; // v
+
+			if (sid.flip_x[i])
+			{
+				float u;
+				u = u0; u0 = u1; u1 = u;
+				u = u2; u2 = u3; u3 = u;
+			}
+
+			if (sid.flip_y[i])
+			{
+				float v;
+				v = v0; v0 = v2; v2 = v;
+				v = v1; v1 = v3; v3 = v;
+			}
+
+			vdata[ 0] = frame[ 0]; // x
+			vdata[ 1] = frame[ 1]; // y
+			vdata[ 2] = u0;
+			vdata[ 3] = v0;
+
+			vdata[ 4] = frame[ 4]; // x
+			vdata[ 5] = frame[ 5]; // y
+			vdata[ 6] = u1;
+			vdata[ 7] = v1;
+
+			vdata[ 8] = frame[ 8]; // x
+			vdata[ 9] = frame[ 9]; // y
+			vdata[10] = u2;
+			vdata[11] = v2;
+
+			vdata[12] = frame[12]; // x
+			vdata[13] = frame[13]; // y
+			vdata[14] = u3;
+			vdata[15] = v3;
+
+			vdata += 16;
 
 			*idata++ = i*4+0;
 			*idata++ = i*4+1;
@@ -666,6 +724,8 @@ void RenderWorld::SpriteManager::allocate(u32 num)
 		+ num*sizeof(u32) + alignof(u32)
 		+ num*sizeof(Matrix4x4) + alignof(Matrix4x4)
 		+ num*sizeof(AABB) + alignof(AABB)
+		+ num*sizeof(bool) + alignof(bool)
+		+ num*sizeof(bool) + alignof(bool)
 		+ num*sizeof(SpriteInstance) + alignof(SpriteInstance)
 		;
 
@@ -681,7 +741,9 @@ void RenderWorld::SpriteManager::allocate(u32 num)
 	new_data.frame         = (u32*                  )memory::align_top(new_data.material + num, alignof(u32                  ));
 	new_data.world         = (Matrix4x4*            )memory::align_top(new_data.frame + num,    alignof(Matrix4x4            ));
 	new_data.aabb          = (AABB*                 )memory::align_top(new_data.world + num,    alignof(AABB                 ));
-	new_data.next_instance = (SpriteInstance*       )memory::align_top(new_data.aabb + num,     alignof(SpriteInstance       ));
+	new_data.flip_x        = (bool*                 )memory::align_top(new_data.aabb + num,     alignof(bool                 ));
+	new_data.flip_y        = (bool*                 )memory::align_top(new_data.flip_x + num,   alignof(bool                 ));
+	new_data.next_instance = (SpriteInstance*       )memory::align_top(new_data.flip_y + num,   alignof(SpriteInstance       ));
 
 	memcpy(new_data.unit, _data.unit, _data.size * sizeof(UnitId));
 	memcpy(new_data.resource, _data.resource, _data.size * sizeof(SpriteResource**));
@@ -689,6 +751,8 @@ void RenderWorld::SpriteManager::allocate(u32 num)
 	memcpy(new_data.frame, _data.frame, _data.size * sizeof(u32));
 	memcpy(new_data.world, _data.world, _data.size * sizeof(Matrix4x4));
 	memcpy(new_data.aabb, _data.aabb, _data.size * sizeof(AABB));
+	memcpy(new_data.flip_x, _data.flip_x, _data.size * sizeof(bool));
+	memcpy(new_data.flip_y, _data.flip_y, _data.size * sizeof(bool));
 	memcpy(new_data.next_instance, _data.next_instance, _data.size * sizeof(SpriteInstance));
 
 	_allocator->deallocate(_data.buffer);
@@ -713,6 +777,8 @@ SpriteInstance RenderWorld::SpriteManager::create(UnitId id, const SpriteResourc
 	_data.frame[last]         = 0;
 	_data.world[last]         = tr;
 	_data.aabb[last]          = AABB();
+	_data.flip_x[last]        = false;
+	_data.flip_y[last]        = false;
 	_data.next_instance[last] = make_instance(UINT32_MAX);
 
 	++_data.size;
@@ -736,6 +802,8 @@ void RenderWorld::SpriteManager::destroy(SpriteInstance i)
 	_data.frame[i.i]         = _data.frame[last];
 	_data.world[i.i]         = _data.world[last];
 	_data.aabb[i.i]          = _data.aabb[last];
+	_data.flip_x[i.i]        = _data.flip_x[last];
+	_data.flip_y[i.i]        = _data.flip_y[last];
 	_data.next_instance[i.i] = _data.next_instance[last];
 
 	--_data.size;

+ 8 - 0
src/world/render_world.h

@@ -65,6 +65,12 @@ public:
 	/// Sets whether the sprite @a i is @a visible.
 	void sprite_set_visible(SpriteInstance i, bool visible);
 
+	/// Sets whether to flip the sprite on the x-axis.
+	void sprite_flip_x(SpriteInstance i, bool flip);
+
+	/// Sets whether to flip the sprite on the y-axis.
+	void sprite_flip_y(SpriteInstance i, bool flip);
+
 	/// Returns the distance along ray (from, dir) to intersection point with sprite @a i
 	/// or -1.0 if no intersection.
 	f32 sprite_raycast(SpriteInstance i, const Vector3& from, const Vector3& dir);
@@ -193,6 +199,8 @@ public:
 			u32* frame;
 			Matrix4x4* world;
 			AABB* aabb;
+			bool* flip_x;
+			bool* flip_y;
 			SpriteInstance* next_instance;
 		};