Skip to content

Commit d5ecf3a

Browse files
committed
Added function to set animations on AnimatedSprite node.
1 parent 71e1901 commit d5ecf3a

File tree

4 files changed

+195
-22
lines changed

4 files changed

+195
-22
lines changed

_version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"version": "0.47.1"
2+
"version": "0.48.0"
33
}

src/core/scripting/python/python_modules.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,84 @@ PyObject* PythonModules::animated_sprite_stop(PyObject *self, PyObject *args, Py
10741074
return nullptr;
10751075
}
10761076

1077+
// TODO: Actually implement!
1078+
PyObject* PythonModules::animated_sprite_get_animations(PyObject *self, PyObject *args, PyObject *kwargs) {
1079+
static EntityComponentOrchestrator *entityComponentOrchestrator = GD::GetContainer()->entityComponentOrchestrator;
1080+
Entity entity;
1081+
if (PyArg_ParseTupleAndKeywords(args, kwargs, "i", nodeGetEntityKWList, &entity)) {
1082+
AnimatedSpriteComponent animatedSpriteComponent = entityComponentOrchestrator->GetComponent<AnimatedSpriteComponent>(entity);
1083+
CPyObject pTagList = PyList_New(0);
1084+
pTagList.AddRef();
1085+
return pTagList;
1086+
}
1087+
return nullptr;
1088+
}
1089+
1090+
PyObject* PythonModules::animated_sprite_set_animations(PyObject *self, PyObject *args, PyObject *kwargs) {
1091+
static EntityComponentOrchestrator *entityComponentOrchestrator = GD::GetContainer()->entityComponentOrchestrator;
1092+
static AssetManager *assetManager = GD::GetContainer()->assetManager;
1093+
Entity entity;
1094+
PyObject *pyList = nullptr;
1095+
if (PyArg_ParseTupleAndKeywords(args, kwargs, "iO", animatedSpriteSetAnimationsKWList, &entity, &pyList)) {
1096+
AnimatedSpriteComponent animatedSpriteComponent = entityComponentOrchestrator->GetComponent<AnimatedSpriteComponent>(entity);
1097+
animatedSpriteComponent.animations.clear();
1098+
std::string firstAnimName;
1099+
for (int i = 0; i < PyList_Size(pyList); i++) {
1100+
CPyObject listTupleItem = PyList_GetItem(pyList, i);
1101+
listTupleItem.AddRef();
1102+
CPyObject pyAnimName = PyTuple_GetItem(listTupleItem, 0);
1103+
pyAnimName.AddRef();
1104+
CPyObject pyAnimSpeed = PyTuple_GetItem(listTupleItem, 1);
1105+
pyAnimSpeed.AddRef();
1106+
CPyObject pyAnimFrames = PyTuple_GetItem(listTupleItem, 2);
1107+
pyAnimFrames.AddRef();
1108+
const std::string& animName = std::string(PyUnicode_AsUTF8(pyAnimName));
1109+
const int animSpeed = PyLong_AsLong(pyAnimSpeed);
1110+
if (i == 0) {
1111+
firstAnimName = animName;
1112+
}
1113+
std::map<unsigned int, AnimationFrame> animationFrames = {};
1114+
for (int j = 0; j < PyList_Size(pyAnimFrames); j++) {
1115+
CPyObject frameTupleItem = PyList_GetItem(pyAnimFrames, j);
1116+
frameTupleItem.AddRef();
1117+
CPyObject pyTextureFilePath = PyTuple_GetItem(frameTupleItem, 0);
1118+
pyTextureFilePath.AddRef();
1119+
CPyObject pyDrawSourceX = PyTuple_GetItem(frameTupleItem, 1);
1120+
pyDrawSourceX.AddRef();
1121+
CPyObject pyDrawSourceY = PyTuple_GetItem(frameTupleItem, 2);
1122+
pyDrawSourceY.AddRef();
1123+
CPyObject pyDrawSourceW = PyTuple_GetItem(frameTupleItem, 3);
1124+
pyDrawSourceW.AddRef();
1125+
CPyObject pyDrawSourceH = PyTuple_GetItem(frameTupleItem, 4);
1126+
pyDrawSourceH.AddRef();
1127+
CPyObject pyIndex = PyTuple_GetItem(frameTupleItem, 5);
1128+
pyIndex.AddRef();
1129+
const std::string& frameTextureFilePath = std::string(PyUnicode_AsUTF8(pyTextureFilePath));
1130+
const float frameDrawSourceX = PyLong_AsLong(pyDrawSourceX);
1131+
const float frameDrawSourceY = PyLong_AsLong(pyDrawSourceY);
1132+
const float frameDrawSourceW = PyLong_AsLong(pyDrawSourceW);
1133+
const float frameDrawSourceH = PyLong_AsLong(pyDrawSourceH);
1134+
const int frameIndex = PyLong_AsLong(pyIndex);
1135+
animationFrames.emplace(frameIndex, AnimationFrame{
1136+
assetManager->GetTexture(frameTextureFilePath),
1137+
Rect2(frameDrawSourceX, frameDrawSourceY, frameDrawSourceW, frameDrawSourceH),
1138+
frameIndex
1139+
});
1140+
}
1141+
animatedSpriteComponent.animations.emplace(animName, Animation{
1142+
animName, animSpeed, animationFrames, animationFrames.size()
1143+
});
1144+
}
1145+
animatedSpriteComponent.currentFrameIndex = 0;
1146+
if (animatedSpriteComponent.animations.size() > 0) {
1147+
animatedSpriteComponent.currentAnimation = animatedSpriteComponent.animations[firstAnimName];
1148+
}
1149+
entityComponentOrchestrator->UpdateComponent<AnimatedSpriteComponent>(entity, animatedSpriteComponent);
1150+
Py_RETURN_NONE;
1151+
}
1152+
return nullptr;
1153+
}
1154+
10771155
PyObject* PythonModules::animated_sprite_is_playing(PyObject *self, PyObject *args, PyObject *kwargs) {
10781156
static EntityComponentOrchestrator *entityComponentOrchestrator = GD::GetContainer()->entityComponentOrchestrator;
10791157
Entity entity;

src/core/scripting/python/python_modules.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class PythonModules {
8888
static PyObject* animated_sprite_play(PyObject* self, PyObject* args, PyObject* kwargs);
8989
static PyObject* animated_sprite_set_animation(PyObject* self, PyObject* args, PyObject* kwargs);
9090
static PyObject* animated_sprite_stop(PyObject* self, PyObject* args, PyObject* kwargs);
91+
static PyObject* animated_sprite_get_animations(PyObject* self, PyObject* args, PyObject* kwargs);
92+
static PyObject* animated_sprite_set_animations(PyObject* self, PyObject* args, PyObject* kwargs);
9193
static PyObject* animated_sprite_is_playing(PyObject* self, PyObject* args, PyObject* kwargs);
9294
static PyObject* animated_sprite_get_modulate(PyObject* self, PyObject* args, PyObject* kwargs);
9395
static PyObject* animated_sprite_set_modulate(PyObject* self, PyObject* args, PyObject* kwargs);
@@ -455,6 +457,14 @@ static struct PyMethodDef rollApiMethods[] = {
455457
"animated_sprite_stop", (PyCFunction) PythonModules::animated_sprite_stop,
456458
METH_VARARGS | METH_KEYWORDS, "Stops animation."
457459
},
460+
{
461+
"animated_sprite_get_animations", (PyCFunction) PythonModules::animated_sprite_get_animations,
462+
METH_VARARGS | METH_KEYWORDS, "Gets all entity's animations."
463+
},
464+
{
465+
"animated_sprite_set_animations", (PyCFunction) PythonModules::animated_sprite_set_animations,
466+
METH_VARARGS | METH_KEYWORDS, "Sets all animations for entity."
467+
},
458468
{
459469
"animated_sprite_is_playing", (PyCFunction) PythonModules::animated_sprite_is_playing,
460470
METH_VARARGS | METH_KEYWORDS, "Returns if an animations is playing."
@@ -736,6 +746,7 @@ static char *spriteSetTextureKWList[] = {"entity_id", "file_path", nullptr};
736746
static char *spriteSetDrawSourceKWList[] = {"entity_id", "x", "y", "w", "h", nullptr};
737747

738748
static char *animatedSpriteAnimationUpdateKWList[] = {"entity_id", "animation_name", nullptr};
749+
static char *animatedSpriteSetAnimationsKWList[] = {"entity_id", "animations", nullptr};
739750
static char *animatedSpriteSetFrameKWList[] = {"entity_id", "frame", nullptr};
740751

741752
static char *textLabelSetTextKWList[] = {"entity_id", "text", nullptr};

src/core/scripting/python/python_source.h

Lines changed: 105 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
#ifndef PYTHON_SOURCE_H
22
#define PYTHON_SOURCE_H
33

4-
// Seika Engine API v0.11.1
4+
// Seika Engine API v0.12.0
55

66
using PythonSource = const std::string&;
77

88
static PythonSource PYTHON_SOURCE_ASSETS_MODULE =
99
"from enum import Enum\n"
10+
"from typing import List\n"
11+
"\n"
1012
"import seika_engine_api\n"
1113
"from seika.color import Color\n"
12-
"from seika.math import Vector2\n"
14+
"from seika.math import Vector2, Rect2\n"
1315
"\n"
1416
"\n"
1517
"class Texture:\n"
@@ -87,22 +89,6 @@ static PythonSource PYTHON_SOURCE_ASSETS_MODULE =
8789
" height=height,\n"
8890
" )\n"
8991
"\n"
90-
" # @staticmethod\n"
91-
" # def create(\n"
92-
" # file_path: str,\n"
93-
" # wrap_s=Wrap.CLAMP_TO_BORDER,\n"
94-
" # wrap_t=Wrap.CLAMP_TO_BORDER,\n"
95-
" # filter_min=FILTER.NEAREST,\n"
96-
" # filter_max=FILTER.NEAREST,\n"
97-
" # ):\n"
98-
" # return Texture(\n"
99-
" # file_path=file_path,\n"
100-
" # wrap_s=wrap_s,\n"
101-
" # wrap_t=wrap_t,\n"
102-
" # filter_min=filter_min,\n"
103-
" # filter_max=filter_max,\n"
104-
" # )\n"
105-
"\n"
10692
" def get_pixel_color(self, position: Vector2) -> Color:\n"
10793
" red, green, blue, alpha = seika_engine_api.texture_get_pixel_color(\n"
10894
" file_path=self.file_path, x=position.x, y=position.y\n"
@@ -116,6 +102,20 @@ static PythonSource PYTHON_SOURCE_ASSETS_MODULE =
116102
" return f\"Texture(file_path: {self._file_path}, wrap_s: {self._wrap_s}, wrap_t: {self._wrap_t}, filter_min: {self._filter_min}, filter_min: {self._filter_max}, width: {self._width}, height: {self._height})\"\n"
117103
"\n"
118104
"\n"
105+
"class AnimationFrame:\n"
106+
" def __init__(self, texture: Texture, draw_source: Rect2, index: int):\n"
107+
" self.texture = texture\n"
108+
" self.draw_source = draw_source\n"
109+
" self.index = index\n"
110+
"\n"
111+
"\n"
112+
"class Animation:\n"
113+
" def __init__(self, name: str, speed: int, frames: List[AnimationFrame]):\n"
114+
" self.name = name\n"
115+
" self.speed = speed\n"
116+
" self.frames = frames\n"
117+
"\n"
118+
"\n"
119119
"class Font:\n"
120120
" def __init__(self, uid: str, file_path: str, size: int):\n"
121121
" self._uid = uid\n"
@@ -885,9 +885,9 @@ static PythonSource PYTHON_SOURCE_NETWORK_MODULE =
885885

886886
static PythonSource PYTHON_SOURCE_NODE_MODULE =
887887
"from enum import Enum\n"
888-
"from typing import Optional\n"
888+
"from typing import Optional, List\n"
889889
"import seika_engine_api\n"
890-
"from seika.assets import Texture, Font\n"
890+
"from seika.assets import Texture, AnimationFrame, Animation, Font\n"
891891
"from seika.math import Vector2, Vector3, Rect2\n"
892892
"from seika.color import Color\n"
893893
"\n"
@@ -1204,6 +1204,88 @@ static PythonSource PYTHON_SOURCE_NODE_MODULE =
12041204
" seika_engine_api.animated_sprite_stop(entity_id=self.entity_id)\n"
12051205
"\n"
12061206
" @property\n"
1207+
" def current_animation(self) -> Animation:\n"
1208+
" return Animation(name=\"\", speed=200, frames=[])\n"
1209+
"\n"
1210+
" @current_animation.setter\n"
1211+
" def current_animation(self, value: Animation) -> None:\n"
1212+
" seika_engine_api.animated_sprite_set_animation(\n"
1213+
" entity_id=self.entity_id, animation_name=value.name\n"
1214+
" )\n"
1215+
"\n"
1216+
" @property\n"
1217+
" def animations(self) -> List[Animation]:\n"
1218+
" # def get_mock_animations() -> list:\n"
1219+
" # mock_animations = [\n"
1220+
" # [\n"
1221+
" # (\n"
1222+
" # # Animation Name\n"
1223+
" # \"idle\",\n"
1224+
" # # Animation Speed\n"
1225+
" # 200,\n"
1226+
" # # Animation Frames\n"
1227+
" # [\n"
1228+
" # (\n"
1229+
" # # Texture Path\n"
1230+
" # \"assets/images/mock.png\",\n"
1231+
" # # Draw Source\n"
1232+
" # 0,\n"
1233+
" # 0,\n"
1234+
" # 16,\n"
1235+
" # 16,\n"
1236+
" # # index\n"
1237+
" # 0,\n"
1238+
" # )\n"
1239+
" # ],\n"
1240+
" # )\n"
1241+
" # ]\n"
1242+
" # ]\n"
1243+
" # return mock_animations\n"
1244+
"\n"
1245+
" received_animations = []\n"
1246+
" for (\n"
1247+
" anim_name,\n"
1248+
" anim_speed,\n"
1249+
" anim_frames,\n"
1250+
" ) in seika_engine_api.animates_sprite_get_animations(entity_id=self.entity_id):\n"
1251+
" in_anim_frames = []\n"
1252+
" for frame_texture_path, x, y, w, h, frame_index in anim_frames:\n"
1253+
" frame_draw_source = Rect2(x, y, w, h)\n"
1254+
" in_anim_frames.append(\n"
1255+
" AnimationFrame(\n"
1256+
" texture=Texture.get(frame_texture_path),\n"
1257+
" draw_source=frame_draw_source,\n"
1258+
" index=frame_index,\n"
1259+
" )\n"
1260+
" )\n"
1261+
" received_animations.append(\n"
1262+
" Animation(name=anim_name, speed=anim_speed, frames=in_anim_frames)\n"
1263+
" )\n"
1264+
"\n"
1265+
" return received_animations\n"
1266+
"\n"
1267+
" @animations.setter\n"
1268+
" def animations(self, value: List[Animation]) -> None:\n"
1269+
" new_anims = []\n"
1270+
" for anim in value:\n"
1271+
" anim_frames = []\n"
1272+
" for anim_frame in anim.frames:\n"
1273+
" anim_frames.append(\n"
1274+
" (\n"
1275+
" anim_frame.texture.file_path,\n"
1276+
" anim_frame.draw_source.x,\n"
1277+
" anim_frame.draw_source.y,\n"
1278+
" anim_frame.draw_source.w,\n"
1279+
" anim_frame.draw_source.h,\n"
1280+
" anim_frame.index,\n"
1281+
" )\n"
1282+
" )\n"
1283+
" new_anims.append((anim.name, anim.speed, anim_frames))\n"
1284+
" seika_engine_api.animated_sprite_set_animations(\n"
1285+
" entity_id=self.entity_id, animations=new_anims\n"
1286+
" )\n"
1287+
"\n"
1288+
" @property\n"
12071289
" def is_playing(self) -> bool:\n"
12081290
" return seika_engine_api.animated_is_playing(entity_id=self.entity_id)\n"
12091291
"\n"
@@ -1561,7 +1643,9 @@ static PythonSource PYTHON_SOURCE_SCENE_MODULE =
15611643

15621644
static PythonSource PYTHON_SOURCE_UTILS_MODULE =
15631645
"class SimpleTimer:\n"
1564-
" def __init__(self, wait_time: float, loops=False, timeout_func=None, start_on_init=False):\n"
1646+
" def __init__(\n"
1647+
" self, wait_time: float, loops=False, timeout_func=None, start_on_init=False\n"
1648+
" ):\n"
15651649
" self.wait_time = wait_time\n"
15661650
" self.loops = loops\n"
15671651
" self.timeout_func = timeout_func\n"

0 commit comments

Comments
 (0)