it's kind of finished
This commit is contained in:
		
							
								
								
									
										28
									
								
								src/COMMON.h
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/COMMON.h
									
									
									
									
									
								
							@@ -108,17 +108,35 @@ static inline s32 map_next_id_get(const std::map<s32, T>& map) {
 | 
				
			|||||||
    s32 id = 0; for (const auto& [key, _] : map) if (key != id) break; else ++id; return id;
 | 
					    s32 id = 0; for (const auto& [key, _] : map) if (key != id) break; else ++id; return id;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Swaps elements in a map */
 | 
				
			||||||
 | 
					/* If neither key exists, do nothing */
 | 
				
			||||||
 | 
					/* If one key exists, change its ID */
 | 
				
			||||||
 | 
					/* If both keys exist, swap */
 | 
				
			||||||
template<typename Map, typename Key>
 | 
					template<typename Map, typename Key>
 | 
				
			||||||
static inline void map_swap(Map& map, const Key& key1, const Key& key2)
 | 
					static inline void map_swap(Map& map, const Key& key1, const Key& key2)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    if (key1 == key2)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    auto it1 = map.find(key1);
 | 
					    auto it1 = map.find(key1);
 | 
				
			||||||
    auto it2 = map.find(key2);
 | 
					    auto it2 = map.find(key2);
 | 
				
			||||||
    if (it1 == map.end() || it2 == map.end())
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    using std::swap;
 | 
					    if (it1 != map.end() && it2 != map.end()) 
 | 
				
			||||||
    swap(it1->second, it2->second);
 | 
					    {
 | 
				
			||||||
}
 | 
					        using std::swap;
 | 
				
			||||||
 | 
					        swap(it1->second, it2->second);
 | 
				
			||||||
 | 
					    } 
 | 
				
			||||||
 | 
					    else if (it1 != map.end()) 
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        map[key2] = std::move(it1->second);
 | 
				
			||||||
 | 
					        map.erase(it1);
 | 
				
			||||||
 | 
					    } 
 | 
				
			||||||
 | 
					    else if (it2 != map.end()) 
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        map[key1] = std::move(it2->second);
 | 
				
			||||||
 | 
					        map.erase(it2);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFINE_ENUM_TO_STRING_FN(fn_name, arr, count) \
 | 
					#define DEFINE_ENUM_TO_STRING_FN(fn_name, arr, count) \
 | 
				
			||||||
    static inline const char* fn_name(s32 index) {   \
 | 
					    static inline const char* fn_name(s32 index) {   \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,13 +62,15 @@
 | 
				
			|||||||
#define STRING_IMGUI_ANIMATIONS_REMOVE "Remove"
 | 
					#define STRING_IMGUI_ANIMATIONS_REMOVE "Remove"
 | 
				
			||||||
#define STRING_IMGUI_ANIMATIONS_DUPLICATE "Duplicate"
 | 
					#define STRING_IMGUI_ANIMATIONS_DUPLICATE "Duplicate"
 | 
				
			||||||
#define STRING_IMGUI_ANIMATIONS_SET_AS_DEFAULT "Set as Default"
 | 
					#define STRING_IMGUI_ANIMATIONS_SET_AS_DEFAULT "Set as Default"
 | 
				
			||||||
#define STRING_IMGUI_ANIMATIONS_DEFAULT_ANIMATION_FORMAT "%s (*)"
 | 
					#define STRING_IMGUI_ANIMATIONS_DEFAULT_ANIMATION_FORMAT "(*) %s "
 | 
				
			||||||
 | 
					#define STRING_IMGUI_ANIMATIONS_DRAG_DROP "Animation Drag/Drop"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_IMGUI_EVENTS "Events"
 | 
					#define STRING_IMGUI_EVENTS "Events"
 | 
				
			||||||
#define STRING_IMGUI_EVENTS_EVENT_LABEL "##Event"
 | 
					#define STRING_IMGUI_EVENTS_EVENT_LABEL "##Event"
 | 
				
			||||||
#define STRING_IMGUI_EVENTS_ADD "Add"
 | 
					#define STRING_IMGUI_EVENTS_ADD "Add"
 | 
				
			||||||
#define STRING_IMGUI_EVENTS_REMOVE "Remove"
 | 
					#define STRING_IMGUI_EVENTS_REMOVE "Remove"
 | 
				
			||||||
#define STRING_IMGUI_EVENT_FORMAT "#%i %s"
 | 
					#define STRING_IMGUI_EVENT_FORMAT "#%i %s"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_EVENTS_DRAG_DROP "Event Drag/Drop"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEETS "Spritesheets"
 | 
					#define STRING_IMGUI_SPRITESHEETS "Spritesheets"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEETS_ADD "Add"
 | 
					#define STRING_IMGUI_SPRITESHEETS_ADD "Add"
 | 
				
			||||||
@@ -76,6 +78,7 @@
 | 
				
			|||||||
#define STRING_IMGUI_SPRITESHEETS_RELOAD "Reload"
 | 
					#define STRING_IMGUI_SPRITESHEETS_RELOAD "Reload"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEETS_REPLACE "Replace"
 | 
					#define STRING_IMGUI_SPRITESHEETS_REPLACE "Replace"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_FORMAT "#%i %s"
 | 
					#define STRING_IMGUI_SPRITESHEET_FORMAT "#%i %s"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_SPRITESHEETS_DRAG_DROP "Spritesheet Drag/Drop"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_IMGUI_FRAME_PROPERTIES "Frame Properties"
 | 
					#define STRING_IMGUI_FRAME_PROPERTIES "Frame Properties"
 | 
				
			||||||
#define STRING_IMGUI_FRAME_PROPERTIES_CROP_POSITION "Crop Position"
 | 
					#define STRING_IMGUI_FRAME_PROPERTIES_CROP_POSITION "Crop Position"
 | 
				
			||||||
@@ -116,12 +119,15 @@
 | 
				
			|||||||
#define STRING_IMGUI_ANIMATION_PREVIEW_AXIS_COLOR "Color"
 | 
					#define STRING_IMGUI_ANIMATION_PREVIEW_AXIS_COLOR "Color"
 | 
				
			||||||
#define STRING_IMGUI_ANIMATION_PREVIEW_ROOT_TRANSFORM "Root Transform"
 | 
					#define STRING_IMGUI_ANIMATION_PREVIEW_ROOT_TRANSFORM "Root Transform"
 | 
				
			||||||
#define STRING_IMGUI_ANIMATION_PREVIEW_SHOW_PIVOT "Show Pivot"
 | 
					#define STRING_IMGUI_ANIMATION_PREVIEW_SHOW_PIVOT "Show Pivot"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_ANIMATION_PREVIEW_POSITION "##Position"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_ANIMATION_PREVIEW_POSITION_FORMAT "Position: {%5.0f, %5.0f}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR "Spritesheet Editor"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR "Spritesheet Editor"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_LABEL "##Animation Preview"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_LABEL "##Animation Preview"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_SETTINGS "##Animation Preview Settings"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_SETTINGS "##Animation Preview Settings"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_SETTINGS "##Grid Settings"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_SETTINGS "##Grid Settings"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID "Grid"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID "Grid"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_SNAP "Snap"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_SIZE "Size"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_SIZE "Size"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_OFFSET "Offset"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_OFFSET "Offset"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_COLOR "Color"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_GRID_COLOR "Color"
 | 
				
			||||||
@@ -131,6 +137,8 @@
 | 
				
			|||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_BACKGROUND_COLOR "Background Color"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_BACKGROUND_COLOR "Background Color"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW "Center View"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_CENTER_VIEW "Center View"
 | 
				
			||||||
#define STRING_IMGUI_SPRITESHEET_EDITOR_BORDER "Border"
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_BORDER "Border"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_POSITION "##Position"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_SPRITESHEET_EDITOR_POSITION_FORMAT "Position: {%5.0f, %5.0f}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_IMGUI_TIMELINE "Timeline"
 | 
					#define STRING_IMGUI_TIMELINE "Timeline"
 | 
				
			||||||
#define STRING_IMGUI_TIMELINE_HEADER "##Header"
 | 
					#define STRING_IMGUI_TIMELINE_HEADER "##Header"
 | 
				
			||||||
@@ -178,6 +186,8 @@
 | 
				
			|||||||
#define STRING_IMGUI_TIMELINE_VIEWER "Viewer"
 | 
					#define STRING_IMGUI_TIMELINE_VIEWER "Viewer"
 | 
				
			||||||
#define STRING_IMGUI_TIMELINE_CHILD "Timeline"
 | 
					#define STRING_IMGUI_TIMELINE_CHILD "Timeline"
 | 
				
			||||||
#define STRING_IMGUI_TIMELINE_MAIN "Main"
 | 
					#define STRING_IMGUI_TIMELINE_MAIN "Main"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_TIMELINE_FRAME_DRAG_DROP "Frame Drag/Drop"
 | 
				
			||||||
 | 
					#define STRING_IMGUI_TIMELINE_ITEM_DRAG_DROP "Item Drag/Drop"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_IMGUI_TOOLS "Tools"
 | 
					#define STRING_IMGUI_TOOLS "Tools"
 | 
				
			||||||
#define STRING_IMGUI_TOOLS_PAN "##Pan"
 | 
					#define STRING_IMGUI_TOOLS_PAN "##Pan"
 | 
				
			||||||
@@ -190,7 +200,7 @@
 | 
				
			|||||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_DUPLICATE "Duplicates the selected animation."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATIONS_DUPLICATE "Duplicates the selected animation."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_REMOVE "Removes the selected animation."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATIONS_REMOVE "Removes the selected animation."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_SELECT "Select the animation to edit.\nYou can also click the name to edit it."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATIONS_SELECT "Select the animation to edit.\nYou can also click the name to edit it."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATIONS_SET_AS_DEFAULT "Sets the selected animation as the default.\nDefault animations are marked with \"(*)\"."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATIONS_SET_AS_DEFAULT "Sets the selected animation as the default.\nThe default animation is marked with \"(*)\"."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_AXIS "Toggles the display of the X/Y axes on the animation preview."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_AXIS "Toggles the display of the X/Y axes on the animation preview."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_AXIS_COLOR "Changes the color of the X/Y axes on the animation preview."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_AXIS_COLOR "Changes the color of the X/Y axes on the animation preview."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_BACKGROUND_COLOR "Changes the background color of the animation preview."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_BACKGROUND_COLOR "Changes the background color of the animation preview."
 | 
				
			||||||
@@ -200,7 +210,7 @@
 | 
				
			|||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_OFFSET "Changes the animation preview grid's offset, in pixels."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_OFFSET "Changes the animation preview grid's offset, in pixels."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_SIZE "Changes the animation preview grid's size, in pixels."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_GRID_SIZE "Changes the animation preview grid's size, in pixels."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_ZOOM "Changes the animation preview zoom level."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_ZOOM "Changes the animation preview zoom level."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_ROOT_TRANSFORM "Toggle the properties of the Root element of an animation being able to change the properties (such as position or scale) of all of the animation's elements." 
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_ROOT_TRANSFORM "Toggle the properties of the Root element of an animation being able to change the properties (such as position or scale) of all of the animation's elements.\nNOTE: Scale/rotation currently not implemented. Matrix math is hard." 
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_SHOW_PIVOT "Toggle the pivots of layer animation elements being visible on the animation preview."
 | 
					#define STRING_IMGUI_TOOLTIP_ANIMATION_PREVIEW_SHOW_PIVOT "Toggle the pivots of layer animation elements being visible on the animation preview."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_EVENTS_ADD "Add a new event."
 | 
					#define STRING_IMGUI_TOOLTIP_EVENTS_ADD "Add a new event."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_EVENTS_REMOVE "Removes the selected event."
 | 
					#define STRING_IMGUI_TOOLTIP_EVENTS_REMOVE "Removes the selected event."
 | 
				
			||||||
@@ -251,16 +261,17 @@
 | 
				
			|||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_BACKGROUND_COLOR "Changes the background color of the spritesheet editor."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_BACKGROUND_COLOR "Changes the background color of the spritesheet editor."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_CENTER_VIEW "Centers the spritesheet editor's pan."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_CENTER_VIEW "Centers the spritesheet editor's pan."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID "Toggles grid visibility on the spritesheet editor."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID "Toggles grid visibility on the spritesheet editor."
 | 
				
			||||||
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_SNAP "When using the crop tool, will snap points to the grid."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_COLOR "Changes the spritesheet editor grid color."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_COLOR "Changes the spritesheet editor grid color."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_OFFSET "Changes the spritesheet editor grid's offset, in pixels."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_OFFSET "Changes the spritesheet editor grid's offset, in pixels."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_SIZE "Changes the spritesheet editor grid's size, in pixels."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_GRID_SIZE "Changes the spritesheet editor grid's size, in pixels."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_ZOOM "Changes the spritesheet editor zoom level."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_ZOOM "Changes the spritesheet editor zoom level."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_BORDER "Toggles a border appearing around the confines of the spritesheet."
 | 
					#define STRING_IMGUI_TOOLTIP_SPRITESHEET_EDITOR_BORDER "Toggles a border appearing around the confines of the spritesheet."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_TOOLS_PAN "Use the pan tool.\nWill shift the view as the cursor is dragged."
 | 
					#define STRING_IMGUI_TOOLTIP_TOOLS_PAN "Use the pan tool.\nWill shift the view as the cursor is dragged."
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_TOOLS_MOVE "Use the move tool.\nWill move selected elements as the cursor is dragged."
 | 
					#define STRING_IMGUI_TOOLTIP_TOOLS_MOVE "Use the move tool.\nWill move selected elements as the cursor is dragged.\n(Animation Preview only.)"
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_TOOLS_ROTATE "Use the rotate tool.\nWill rotate selected elements as the cursor is dragged."
 | 
					#define STRING_IMGUI_TOOLTIP_TOOLS_ROTATE "Use the rotate tool.\nWill rotate selected elements as the cursor is dragged.\n(Animation Preview only.)"
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_TOOLS_SCALE "Use the scale tool.\nWill scale the selected elements as the cursor is dragged."
 | 
					#define STRING_IMGUI_TOOLTIP_TOOLS_SCALE "Use the scale tool.\nWill scale the selected elements as the cursor is dragged.\n(Animation Preview only.)"
 | 
				
			||||||
#define STRING_IMGUI_TOOLTIP_TOOLS_CROP "Use the crop tool.\nWill set the crop of the selected elements as the cursor is dragged."
 | 
					#define STRING_IMGUI_TOOLTIP_TOOLS_CROP "Use the crop tool.\nWill set the crop of the selected elements as the cursor is dragged.\n(Spritesheet Editor only.)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STRING_OPENGL_VERSION "#version 330"
 | 
					#define STRING_OPENGL_VERSION "#version 330"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										476
									
								
								src/anm2.cpp
									
									
									
									
									
								
							
							
						
						
									
										476
									
								
								src/anm2.cpp
									
									
									
									
									
								
							@@ -37,7 +37,6 @@ anm2_serialize(Anm2* self, const char* path)
 | 
				
			|||||||
	if (!self || !path)
 | 
						if (!self || !path)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Update creation date on first version */
 | 
						/* Update creation date on first version */
 | 
				
			||||||
	if (self->version == 0)
 | 
						if (self->version == 0)
 | 
				
			||||||
		anm2_created_on_set(self);
 | 
							anm2_created_on_set(self);
 | 
				
			||||||
@@ -45,8 +44,6 @@ anm2_serialize(Anm2* self, const char* path)
 | 
				
			|||||||
	/* Increment anm2's version */
 | 
						/* Increment anm2's version */
 | 
				
			||||||
	self->version++;
 | 
						self->version++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Set the anm2's date to the system time */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* AnimatedActor */
 | 
						/* AnimatedActor */
 | 
				
			||||||
	animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
 | 
						animatedActorElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
 | 
				
			||||||
	document.InsertFirstChild(animatedActorElement);
 | 
						document.InsertFirstChild(animatedActorElement);
 | 
				
			||||||
@@ -283,14 +280,14 @@ anm2_serialize(Anm2* self, const char* path)
 | 
				
			|||||||
		/* Triggers */
 | 
							/* Triggers */
 | 
				
			||||||
		triggersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]);
 | 
							triggersElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGERS]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for (auto & trigger : animation.triggers.items)
 | 
							for (auto & frame : animation.triggers.frames)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			XMLElement* triggerElement;
 | 
								XMLElement* triggerElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* Trigger */
 | 
								/* Trigger */
 | 
				
			||||||
			triggerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]);
 | 
								triggerElement = document.NewElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_TRIGGER]);
 | 
				
			||||||
			triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], trigger.eventID); /* EventID */
 | 
								triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_EVENT_ID], frame.eventID); /* EventID */
 | 
				
			||||||
			triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], trigger.atFrame); /* AtFrame */
 | 
								triggerElement->SetAttribute(ANM2_ATTRIBUTE_STRINGS[ANM2_ATTRIBUTE_AT_FRAME], frame.atFrame); /* AtFrame */
 | 
				
			||||||
			triggersElement->InsertEndChild(triggerElement);
 | 
								triggersElement->InsertEndChild(triggerElement);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -321,35 +318,27 @@ anm2_serialize(Anm2* self, const char* path)
 | 
				
			|||||||
bool 
 | 
					bool 
 | 
				
			||||||
anm2_deserialize(Anm2* self, Resources* resources, const char* path)
 | 
					anm2_deserialize(Anm2* self, Resources* resources, const char* path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	XMLDocument document;
 | 
						XMLDocument xmlDocument;
 | 
				
			||||||
	XMLError error;
 | 
						XMLError xmlError;
 | 
				
			||||||
	const XMLElement* element;
 | 
						const XMLElement* xmlElement;
 | 
				
			||||||
	const XMLElement* root;
 | 
						const XMLElement* xmlRoot;
 | 
				
			||||||
	Anm2Spritesheet* lastSpritesheet = NULL;
 | 
						Anm2Animation* animation = NULL;
 | 
				
			||||||
	Anm2Layer* lastLayer = NULL;
 | 
						Anm2Layer* layer = NULL;
 | 
				
			||||||
	Anm2Null* lastNull = NULL;
 | 
						Anm2Null* null = NULL;
 | 
				
			||||||
	Anm2Event* lastEvent = NULL;
 | 
						Anm2Item* item = NULL;
 | 
				
			||||||
	Anm2Animation* lastAnimation = NULL;
 | 
						Anm2Event* event = NULL;
 | 
				
			||||||
	Anm2LayerAnimation* lastLayerAnimation = NULL;
 | 
						Anm2Frame* frame = NULL;
 | 
				
			||||||
	Anm2NullAnimation* lastNullAnimation = NULL;
 | 
						Anm2Spritesheet* spritesheet = NULL;
 | 
				
			||||||
	Anm2Frame* lastFrame = NULL;
 | 
					 | 
				
			||||||
	Anm2Trigger* lastTrigger = NULL;
 | 
					 | 
				
			||||||
	Anm2Element anm2Element = ANM2_ELEMENT_ANIMATED_ACTOR;
 | 
						Anm2Element anm2Element = ANM2_ELEMENT_ANIMATED_ACTOR;
 | 
				
			||||||
	Anm2Attribute anm2Attribute =  ANM2_ATTRIBUTE_ID;
 | 
						Anm2Attribute anm2Attribute =  ANM2_ATTRIBUTE_ID;
 | 
				
			||||||
	Anm2AnimationType animationType = ANM2_ROOT_ANIMATION;
 | 
					 | 
				
			||||||
	Anm2Null tempNull;
 | 
					 | 
				
			||||||
	Anm2Layer tempLayer;
 | 
					 | 
				
			||||||
	Anm2Spritesheet tempSpritesheet;
 | 
					 | 
				
			||||||
	Anm2Event tempEvent;
 | 
					 | 
				
			||||||
	char lastSpritesheetPath[PATH_MAX];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*self = Anm2{};
 | 
						*self = Anm2{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = document.LoadFile(path);
 | 
						xmlError = xmlDocument.LoadFile(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (error != XML_SUCCESS)
 | 
						if (xmlError != XML_SUCCESS)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		printf(STRING_ERROR_ANM2_READ, path, document.ErrorStr());
 | 
							printf(STRING_ERROR_ANM2_READ, path, xmlDocument.ErrorStr());
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -357,297 +346,252 @@ anm2_deserialize(Anm2* self, Resources* resources, const char* path)
 | 
				
			|||||||
	strncpy(self->path, path, PATH_MAX - 1);
 | 
						strncpy(self->path, path, PATH_MAX - 1);
 | 
				
			||||||
	working_directory_from_path_set(path);
 | 
						working_directory_from_path_set(path);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
    root = document.FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
 | 
					    xmlRoot = xmlDocument.FirstChildElement(ANM2_ELEMENT_STRINGS[ANM2_ELEMENT_ANIMATED_ACTOR]);
 | 
				
			||||||
	element = root;
 | 
						xmlElement = xmlRoot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (element)
 | 
						while (xmlElement)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		const XMLAttribute* attribute;
 | 
					
 | 
				
			||||||
		const XMLElement* child;
 | 
							const XMLAttribute* xmlAttribute = NULL;
 | 
				
			||||||
		s32 id;
 | 
							const XMLElement* xmlChild = NULL;
 | 
				
			||||||
 | 
							s32 id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Elements */
 | 
							/* Elements */
 | 
				
			||||||
		anm2Element = anm2_element_from_string(element->Name());
 | 
							anm2Element = anm2_element_from_string(xmlElement->Name());
 | 
				
			||||||
			
 | 
					
 | 
				
			||||||
		switch (anm2Element)
 | 
							switch (anm2Element)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			case ANM2_ELEMENT_SPRITESHEET:
 | 
								case ANM2_ELEMENT_SPRITESHEET:
 | 
				
			||||||
				lastSpritesheet = &tempSpritesheet;
 | 
									id = map_next_id_get(self->spritesheets);
 | 
				
			||||||
 | 
									self->spritesheets[id] = Anm2Spritesheet{};
 | 
				
			||||||
 | 
									spritesheet = &self->spritesheets[id];
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_LAYER:
 | 
								case ANM2_ELEMENT_LAYER:
 | 
				
			||||||
				lastLayer = &tempLayer;
 | 
									id = map_next_id_get(self->layers);
 | 
				
			||||||
 | 
									self->layers[id] = Anm2Layer{};
 | 
				
			||||||
 | 
									layer = &self->layers[id];
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_NULL:
 | 
								case ANM2_ELEMENT_NULL:
 | 
				
			||||||
				lastNull = &tempNull;
 | 
									id = map_next_id_get(self->nulls);
 | 
				
			||||||
 | 
									self->nulls[id] = Anm2Null{};
 | 
				
			||||||
 | 
									null = &self->nulls[id];
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_EVENT:
 | 
								case ANM2_ELEMENT_EVENT:
 | 
				
			||||||
				lastEvent = &tempEvent;
 | 
									id = map_next_id_get(self->events);
 | 
				
			||||||
 | 
									self->events[id] = Anm2Event{};
 | 
				
			||||||
 | 
									event = &self->events[id];
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_ANIMATION:
 | 
								case ANM2_ELEMENT_ANIMATION:
 | 
				
			||||||
				id = map_next_id_get(self->animations);
 | 
									id = map_next_id_get(self->animations);
 | 
				
			||||||
				self->animations[id] = Anm2Animation{};
 | 
									self->animations[id] = Anm2Animation{};
 | 
				
			||||||
				lastAnimation = &self->animations[id];
 | 
									animation = &self->animations[id];
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_ROOT_ANIMATION:
 | 
								case ANM2_ELEMENT_ROOT_ANIMATION:
 | 
				
			||||||
				animationType = ANM2_ROOT_ANIMATION;
 | 
									item = &animation->rootAnimation;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_LAYER_ANIMATION:
 | 
								case ANM2_ELEMENT_LAYER_ANIMATION:
 | 
				
			||||||
				animationType = ANM2_LAYER_ANIMATION;
 | 
									id = map_next_id_get(animation->layerAnimations);
 | 
				
			||||||
				lastLayerAnimation = NULL;
 | 
									animation->layerAnimations[id] = Anm2Item{};
 | 
				
			||||||
 | 
									item = &animation->layerAnimations[id];
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_NULL_ANIMATION:
 | 
								case ANM2_ELEMENT_NULL_ANIMATION:
 | 
				
			||||||
				animationType = ANM2_NULL_ANIMATION;
 | 
									id = map_next_id_get(animation->nullAnimations);
 | 
				
			||||||
				lastNullAnimation = NULL;
 | 
									animation->nullAnimations[id] = Anm2Item{};
 | 
				
			||||||
 | 
									item = &animation->nullAnimations[id];
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case ANM2_ELEMENT_TRIGGERS:
 | 
				
			||||||
 | 
									item = &animation->triggers;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			case ANM2_ELEMENT_FRAME:
 | 
								case ANM2_ELEMENT_FRAME:
 | 
				
			||||||
				switch (animationType)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					case ANM2_ROOT_ANIMATION:
 | 
					 | 
				
			||||||
						lastAnimation->rootAnimation.frames.push_back(Anm2Frame{});
 | 
					 | 
				
			||||||
						lastFrame = &lastAnimation->rootAnimation.frames.back();
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					case ANM2_LAYER_ANIMATION:
 | 
					 | 
				
			||||||
						if (!lastLayerAnimation) break;
 | 
					 | 
				
			||||||
						lastLayerAnimation->frames.push_back(Anm2Frame{});
 | 
					 | 
				
			||||||
						lastFrame = &lastLayerAnimation->frames.back();
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
					case ANM2_NULL_ANIMATION:
 | 
					 | 
				
			||||||
						if (!lastNullAnimation) break;
 | 
					 | 
				
			||||||
						lastNullAnimation->frames.push_back(Anm2Frame{});
 | 
					 | 
				
			||||||
						lastFrame = &lastNullAnimation->frames.back();
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
					default:
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case ANM2_ELEMENT_TRIGGER:
 | 
								case ANM2_ELEMENT_TRIGGER:
 | 
				
			||||||
				lastAnimation->triggers.items.push_back(Anm2Trigger{});
 | 
									item->frames.push_back(Anm2Frame{});
 | 
				
			||||||
				lastTrigger = &lastAnimation->triggers.items.back();
 | 
									frame = &item->frames.back();
 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Attributes */
 | 
							/* Attributes */
 | 
				
			||||||
		attribute = element->FirstAttribute();
 | 
							xmlAttribute = xmlElement->FirstAttribute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		while (attribute)
 | 
							while (xmlAttribute)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			anm2Attribute = anm2_attribute_from_string(attribute->Name());
 | 
								anm2Attribute = anm2_attribute_from_string(xmlAttribute->Name());
 | 
				
			||||||
			
 | 
					
 | 
				
			||||||
			switch (anm2Attribute)
 | 
								switch (anm2Attribute)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				case ANM2_ATTRIBUTE_CREATED_BY:
 | 
									case ANM2_ATTRIBUTE_CREATED_BY:
 | 
				
			||||||
					strncpy(self->createdBy, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
										strncpy(self->createdBy, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_CREATED_ON:
 | 
									case ANM2_ATTRIBUTE_CREATED_ON:
 | 
				
			||||||
					strncpy(self->createdOn, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
										strncpy(self->createdOn, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_VERSION:
 | 
									case ANM2_ATTRIBUTE_VERSION:
 | 
				
			||||||
					self->version = atoi(attribute->Value());
 | 
										self->version = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_FPS:
 | 
									case ANM2_ATTRIBUTE_FPS:
 | 
				
			||||||
					self->fps = atoi(attribute->Value());
 | 
										self->fps = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_ID:
 | 
									case ANM2_ATTRIBUTE_ID:
 | 
				
			||||||
					id = atoi(attribute->Value());
 | 
										break;
 | 
				
			||||||
					switch (anm2Element)
 | 
									case ANM2_ATTRIBUTE_LAYER_ID:
 | 
				
			||||||
					{
 | 
										map_swap(animation->layerAnimations, id, atoi(xmlAttribute->Value()));
 | 
				
			||||||
						case ANM2_ELEMENT_SPRITESHEET:
 | 
										break;
 | 
				
			||||||
							self->spritesheets[id] = tempSpritesheet;
 | 
									case ANM2_ATTRIBUTE_NULL_ID:
 | 
				
			||||||
							lastSpritesheet = &self->spritesheets[id];
 | 
										map_swap(animation->nullAnimations, id, atoi(xmlAttribute->Value()));
 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						case ANM2_ELEMENT_LAYER:
 | 
					 | 
				
			||||||
							self->layers[id] = tempLayer;
 | 
					 | 
				
			||||||
							lastLayer = &self->layers[id];
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						case ANM2_ELEMENT_NULL:
 | 
					 | 
				
			||||||
							self->nulls[id] = tempNull;
 | 
					 | 
				
			||||||
							lastNull = &self->nulls[id];
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						case ANM2_ELEMENT_EVENT:
 | 
					 | 
				
			||||||
							self->events[id] = tempEvent;
 | 
					 | 
				
			||||||
							lastEvent = &self->events[id];
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						default:
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_PATH:
 | 
									case ANM2_ATTRIBUTE_PATH:
 | 
				
			||||||
					/* Make path lowercase */
 | 
										strncpy(spritesheet->path, xmlAttribute->Value(), PATH_MAX - 1);
 | 
				
			||||||
					strncpy(lastSpritesheetPath, attribute->Value(), PATH_MAX - 1);
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_NAME:
 | 
									case ANM2_ATTRIBUTE_NAME:
 | 
				
			||||||
					switch (anm2Element)
 | 
										switch (anm2Element)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						case ANM2_ELEMENT_LAYER:
 | 
											case ANM2_ELEMENT_LAYER:
 | 
				
			||||||
							strncpy(lastLayer->name, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
												strncpy(layer->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						case ANM2_ELEMENT_NULL:
 | 
											case ANM2_ELEMENT_NULL:
 | 
				
			||||||
							strncpy(lastNull->name, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
												strncpy(null->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						case ANM2_ELEMENT_ANIMATION:
 | 
											case ANM2_ELEMENT_ANIMATION:
 | 
				
			||||||
							strncpy(lastAnimation->name, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
												strncpy(animation->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						case ANM2_ELEMENT_EVENT:
 | 
											case ANM2_ELEMENT_EVENT:
 | 
				
			||||||
							strncpy(lastEvent->name, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
												strncpy(event->name, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						default:
 | 
											default:
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_SPRITESHEET_ID:
 | 
									case ANM2_ATTRIBUTE_SPRITESHEET_ID:
 | 
				
			||||||
					lastLayer->spritesheetID = atoi(attribute->Value());
 | 
										layer->spritesheetID = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_SHOW_RECT:
 | 
									case ANM2_ATTRIBUTE_SHOW_RECT:
 | 
				
			||||||
					switch (anm2Element)
 | 
										null->isShowRect = string_to_bool(xmlAttribute->Value());
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						case ANM2_ELEMENT_NULL:
 | 
					 | 
				
			||||||
							lastNull->isShowRect = string_to_bool(attribute->Value());
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
						default:
 | 
					 | 
				
			||||||
							break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_DEFAULT_ANIMATION:
 | 
									case ANM2_ATTRIBUTE_DEFAULT_ANIMATION:
 | 
				
			||||||
					strncpy(self->defaultAnimation, attribute->Value(), ANM2_STRING_MAX - 1);
 | 
										strncpy(self->defaultAnimation, xmlAttribute->Value(), ANM2_STRING_MAX - 1);
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_FRAME_NUM:
 | 
									case ANM2_ATTRIBUTE_FRAME_NUM:
 | 
				
			||||||
					lastAnimation->frameNum = atoi(attribute->Value());
 | 
										animation->frameNum = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_LOOP:
 | 
									case ANM2_ATTRIBUTE_LOOP:
 | 
				
			||||||
					lastAnimation->isLoop = string_to_bool(attribute->Value());
 | 
										animation->isLoop = string_to_bool(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_X_POSITION:
 | 
									case ANM2_ATTRIBUTE_X_POSITION:
 | 
				
			||||||
					lastFrame->position.x = atof(attribute->Value());
 | 
										frame->position.x = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_Y_POSITION:
 | 
									case ANM2_ATTRIBUTE_Y_POSITION:
 | 
				
			||||||
					lastFrame->position.y = atof(attribute->Value());
 | 
										frame->position.y = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_X_PIVOT:
 | 
									case ANM2_ATTRIBUTE_X_PIVOT:
 | 
				
			||||||
					lastFrame->pivot.x = atof(attribute->Value());
 | 
										frame->pivot.x = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_Y_PIVOT:
 | 
									case ANM2_ATTRIBUTE_Y_PIVOT:
 | 
				
			||||||
					lastFrame->pivot.y = atof(attribute->Value());
 | 
										frame->pivot.y = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_X_CROP:
 | 
									case ANM2_ATTRIBUTE_X_CROP:
 | 
				
			||||||
					lastFrame->crop.x = atof(attribute->Value());
 | 
										frame->crop.x = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_Y_CROP:
 | 
									case ANM2_ATTRIBUTE_Y_CROP:
 | 
				
			||||||
					lastFrame->crop.y = atof(attribute->Value());
 | 
										frame->crop.y = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;	
 | 
										break;	
 | 
				
			||||||
				case ANM2_ATTRIBUTE_WIDTH:
 | 
									case ANM2_ATTRIBUTE_WIDTH:
 | 
				
			||||||
					lastFrame->size.x = atof(attribute->Value());
 | 
										frame->size.x = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;		
 | 
										break;		
 | 
				
			||||||
				case ANM2_ATTRIBUTE_HEIGHT:
 | 
									case ANM2_ATTRIBUTE_HEIGHT:
 | 
				
			||||||
					lastFrame->size.y = atof(attribute->Value());
 | 
										frame->size.y = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;		
 | 
										break;		
 | 
				
			||||||
				case ANM2_ATTRIBUTE_X_SCALE:
 | 
									case ANM2_ATTRIBUTE_X_SCALE:
 | 
				
			||||||
					lastFrame->scale.x = atof(attribute->Value());
 | 
										frame->scale.x = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_Y_SCALE:
 | 
									case ANM2_ATTRIBUTE_Y_SCALE:
 | 
				
			||||||
					lastFrame->scale.y = atof(attribute->Value());
 | 
										frame->scale.y = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_DELAY:
 | 
									case ANM2_ATTRIBUTE_DELAY:
 | 
				
			||||||
					lastFrame->delay = atoi(attribute->Value());
 | 
										frame->delay = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_VISIBLE:
 | 
									case ANM2_ATTRIBUTE_VISIBLE:
 | 
				
			||||||
					switch (anm2Element)
 | 
										switch (anm2Element)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						case ANM2_ELEMENT_FRAME:
 | 
											case ANM2_ELEMENT_FRAME:
 | 
				
			||||||
							lastFrame->isVisible = string_to_bool(attribute->Value());
 | 
												frame->isVisible = string_to_bool(xmlAttribute->Value());
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						case ANM2_LAYER_ANIMATION:
 | 
											case ANM2_ELEMENT_ROOT_ANIMATION:
 | 
				
			||||||
							lastLayerAnimation->isVisible = string_to_bool(attribute->Value());
 | 
											case ANM2_ELEMENT_LAYER_ANIMATION:
 | 
				
			||||||
							break;
 | 
											case ANM2_ELEMENT_NULL_ANIMATION:
 | 
				
			||||||
						case ANM2_NULL_ANIMATION:
 | 
												item->isVisible = string_to_bool(xmlAttribute->Value());
 | 
				
			||||||
							lastNullAnimation->isVisible = string_to_bool(attribute->Value());
 | 
					 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
						default:
 | 
											default:
 | 
				
			||||||
							break;
 | 
												break;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_RED_TINT:
 | 
									case ANM2_ATTRIBUTE_RED_TINT:
 | 
				
			||||||
					lastFrame->tintRGBA.r = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->tintRGBA.r = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_GREEN_TINT:
 | 
									case ANM2_ATTRIBUTE_GREEN_TINT:
 | 
				
			||||||
					lastFrame->tintRGBA.g = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->tintRGBA.g = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_BLUE_TINT:
 | 
									case ANM2_ATTRIBUTE_BLUE_TINT:
 | 
				
			||||||
					lastFrame->tintRGBA.b = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->tintRGBA.b = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_ALPHA_TINT:
 | 
									case ANM2_ATTRIBUTE_ALPHA_TINT:
 | 
				
			||||||
					lastFrame->tintRGBA.a = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->tintRGBA.a = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_RED_OFFSET:
 | 
									case ANM2_ATTRIBUTE_RED_OFFSET:
 | 
				
			||||||
					lastFrame->offsetRGB.r = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->offsetRGB.r = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_GREEN_OFFSET:
 | 
									case ANM2_ATTRIBUTE_GREEN_OFFSET:
 | 
				
			||||||
					lastFrame->offsetRGB.g = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->offsetRGB.g = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_BLUE_OFFSET:
 | 
									case ANM2_ATTRIBUTE_BLUE_OFFSET:
 | 
				
			||||||
					lastFrame->offsetRGB.b = COLOR_INT_TO_FLOAT(atoi(attribute->Value()));
 | 
										frame->offsetRGB.b = COLOR_INT_TO_FLOAT(atoi(xmlAttribute->Value()));
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_ROTATION:
 | 
									case ANM2_ATTRIBUTE_ROTATION:
 | 
				
			||||||
					lastFrame->rotation = atof(attribute->Value());
 | 
										frame->rotation = atof(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_INTERPOLATED:
 | 
									case ANM2_ATTRIBUTE_INTERPOLATED:
 | 
				
			||||||
					lastFrame->isInterpolated = string_to_bool(attribute->Value());
 | 
										frame->isInterpolated = string_to_bool(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case ANM2_ATTRIBUTE_LAYER_ID:
 | 
					 | 
				
			||||||
					id = atoi(attribute->Value());
 | 
					 | 
				
			||||||
					lastAnimation->layerAnimations[id] = Anm2LayerAnimation{};
 | 
					 | 
				
			||||||
					lastLayerAnimation = &lastAnimation->layerAnimations[id];
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case ANM2_ATTRIBUTE_NULL_ID:
 | 
					 | 
				
			||||||
					id = atoi(attribute->Value());
 | 
					 | 
				
			||||||
					lastAnimation->nullAnimations[id] = Anm2NullAnimation{};
 | 
					 | 
				
			||||||
					lastNullAnimation = &lastAnimation->nullAnimations[id];
 | 
					 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_EVENT_ID:
 | 
									case ANM2_ATTRIBUTE_EVENT_ID:
 | 
				
			||||||
					lastTrigger->eventID = atoi(attribute->Value());
 | 
										frame->eventID = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				case ANM2_ATTRIBUTE_AT_FRAME:
 | 
									case ANM2_ATTRIBUTE_AT_FRAME:
 | 
				
			||||||
					lastTrigger->atFrame = atoi(attribute->Value());
 | 
										frame->atFrame = atoi(xmlAttribute->Value());
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			attribute = attribute->Next();
 | 
								xmlAttribute = xmlAttribute->Next();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Load spritesheet textures */
 | 
							/* Load spritesheet textures */
 | 
				
			||||||
		if (anm2Element == ANM2_ELEMENT_SPRITESHEET)
 | 
							if (anm2Element == ANM2_ELEMENT_SPRITESHEET)
 | 
				
			||||||
		{
 | 
								anm2_spritesheet_texture_load(self, resources, spritesheet->path , id);
 | 
				
			||||||
			strncpy(lastSpritesheet->path, lastSpritesheetPath, PATH_MAX);
 | 
					 | 
				
			||||||
			anm2_spritesheet_texture_load(self, resources, lastSpritesheetPath , id);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Iterate through children */
 | 
							/* Iterate through children */
 | 
				
			||||||
		child = element->FirstChildElement();
 | 
							xmlChild = xmlElement->FirstChildElement();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (child)
 | 
							if (xmlChild)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			element = child;
 | 
								xmlElement = xmlChild;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Iterate through siblings */
 | 
							/* Iterate through siblings */
 | 
				
			||||||
		while (element)
 | 
							while (xmlElement)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			const XMLElement* next;
 | 
								const XMLElement* xmlNext;
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			next = element->NextSiblingElement();
 | 
								xmlNext = xmlElement->NextSiblingElement();
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
			if (next)
 | 
								if (xmlNext)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				element = next;
 | 
									xmlElement = xmlNext;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/* If no siblings, return to parent. If no parent, end parsing */
 | 
								/* If no siblings, return to parent. If no parent, end parsing */
 | 
				
			||||||
			element = element->Parent() ? element->Parent()->ToElement() : NULL;
 | 
								xmlElement = xmlElement->Parent() ? xmlElement->Parent()->ToElement() : NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -665,7 +609,7 @@ anm2_layer_add(Anm2* self)
 | 
				
			|||||||
	self->layers[id] = Anm2Layer{};
 | 
						self->layers[id] = Anm2Layer{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (auto & [animationID, animation] : self->animations)
 | 
						for (auto & [animationID, animation] : self->animations)
 | 
				
			||||||
		animation.layerAnimations[id] = Anm2LayerAnimation{};
 | 
							animation.layerAnimations[id] = Anm2Item{};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Removes a layer from the anm2 given the index/id */
 | 
					/* Removes a layer from the anm2 given the index/id */
 | 
				
			||||||
@@ -674,8 +618,8 @@ anm2_layer_remove(Anm2* self, s32 id)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    self->layers.erase(id);
 | 
					    self->layers.erase(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (auto& animationPair : self->animations)
 | 
					    for (auto & [animationID, animation] : self->animations)
 | 
				
			||||||
        animationPair.second.layerAnimations.erase(id);
 | 
					        animation.layerAnimations.erase(id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Adds a new null to the anm2 */
 | 
					/* Adds a new null to the anm2 */
 | 
				
			||||||
@@ -687,7 +631,7 @@ anm2_null_add(Anm2* self)
 | 
				
			|||||||
	self->nulls[id] = Anm2Null{};
 | 
						self->nulls[id] = Anm2Null{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (auto & [animationID, animation] : self->animations)
 | 
						for (auto & [animationID, animation] : self->animations)
 | 
				
			||||||
		animation.nullAnimations[id] = Anm2NullAnimation{};
 | 
							animation.nullAnimations[id] = Anm2Item{};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Removes a null from the anm2 given the index/id */
 | 
					/* Removes a null from the anm2 given the index/id */
 | 
				
			||||||
@@ -696,8 +640,8 @@ anm2_null_remove(Anm2* self, s32 id)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    self->nulls.erase(id);
 | 
					    self->nulls.erase(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (auto& animationPair : self->animations)
 | 
					    for (auto & [animationID, animation] : self->animations)
 | 
				
			||||||
        animationPair.second.nullAnimations.erase(id);
 | 
					        animation.nullAnimations.erase(id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Adds a new animation to the anm2, makes sure to keep the layeranimations/nullsanimation check */
 | 
					/* Adds a new animation to the anm2, makes sure to keep the layeranimations/nullsanimation check */
 | 
				
			||||||
@@ -710,13 +654,13 @@ anm2_animation_add(Anm2* self)
 | 
				
			|||||||
	/* match layers */
 | 
						/* match layers */
 | 
				
			||||||
    for (auto & [layerID, layer] : self->layers)
 | 
					    for (auto & [layerID, layer] : self->layers)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
        animation.layerAnimations[layerID] = Anm2LayerAnimation{};
 | 
					        animation.layerAnimations[layerID] = Anm2Item{};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* match nulls */
 | 
						/* match nulls */
 | 
				
			||||||
    for (auto & [nullID, null] : self->nulls)
 | 
					    for (auto & [nullID, null] : self->nulls)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
    	animation.nullAnimations[nullID] = Anm2NullAnimation{};
 | 
					    	animation.nullAnimations[nullID] = Anm2Item{};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* add a root frame */
 | 
						/* add a root frame */
 | 
				
			||||||
@@ -757,69 +701,104 @@ anm2_spritesheet_texture_load(Anm2* self, Resources* resources, const char* path
 | 
				
			|||||||
	resources->textures[id] = texture;
 | 
						resources->textures[id] = texture;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Anm2Animation*
 | 
				
			||||||
 | 
					anm2_animation_from_id(Anm2* self, s32 animationID)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto it = self->animations.find(animationID);
 | 
				
			||||||
 | 
						if (it == self->animations.end())
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						return &it->second;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns the item from a anm2 reference. */
 | 
				
			||||||
 | 
					Anm2Item*
 | 
				
			||||||
 | 
					anm2_item_from_reference(Anm2* self, Anm2Reference* reference, s32 animationID)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Anm2Animation* animation = anm2_animation_from_id(self, animationID);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (!animation)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (reference->type)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							case ANM2_ROOT:
 | 
				
			||||||
 | 
								return &animation->rootAnimation;
 | 
				
			||||||
 | 
							case ANM2_LAYER:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto it = animation->layerAnimations.find(reference->id);
 | 
				
			||||||
 | 
								if (it == animation->layerAnimations.end())
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								return &it->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							case ANM2_NULL:
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								auto it = animation->nullAnimations.find(reference->id);
 | 
				
			||||||
 | 
								if (it == animation->nullAnimations.end())
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
								return &it->second;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							case ANM2_TRIGGERS:
 | 
				
			||||||
 | 
								return &animation->triggers;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Gets the frame from the reference's properties */
 | 
				
			||||||
 | 
					Anm2Frame*
 | 
				
			||||||
 | 
					anm2_frame_from_reference(Anm2* self, Anm2Reference* reference, s32 animationID)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Anm2Item* item = anm2_item_from_reference(self, reference, animationID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!item)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reference->index < 0 || reference->index >= (s32)item->frames.size())
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &item->frames[reference->index];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Creates/fetches a frame from a given time. */
 | 
					/* Creates/fetches a frame from a given time. */
 | 
				
			||||||
/* Returns true/false if frame will be valid or not. */
 | 
					/* Returns true/false if frame will be valid or not. */
 | 
				
			||||||
bool
 | 
					void 
 | 
				
			||||||
anm2_frame_from_time(Anm2* self, Anm2Animation* animation, Anm2Frame* frame, Anm2AnimationType type, s32 id, f32 time)
 | 
					anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, s32 animationID, f32 time)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						Anm2Animation* animation = anm2_animation_from_id(self, animationID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Out of range */
 | 
						/* Out of range */
 | 
				
			||||||
	if (time < 0 || time > animation->frameNum)
 | 
						if (time < 0 || time > animation->frameNum)
 | 
				
			||||||
		return false;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Anm2Item* item = anm2_item_from_reference(self, &reference, animationID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!item)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Anm2RootAnimation* rootAnimation;
 | 
					 | 
				
			||||||
	Anm2LayerAnimation* layerAnimation;
 | 
					 | 
				
			||||||
	Anm2NullAnimation* nullAnimation;
 | 
					 | 
				
			||||||
	Anm2Frame* nextFrame = NULL;
 | 
						Anm2Frame* nextFrame = NULL;
 | 
				
			||||||
	std::vector<Anm2Frame>* frames = NULL;
 | 
						s32 delayCurrent = 0;
 | 
				
			||||||
	f32 delayCurrent = 0;
 | 
						s32 delayNext = 0;
 | 
				
			||||||
	f32 delayNext = 0;
 | 
					 | 
				
			||||||
	bool isTimeMatchedFrame = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (type)
 | 
						for (s32 i = 0; i < (s32)item->frames.size(); i++)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		case ANM2_ROOT_ANIMATION:
 | 
							*frame = item->frames[i];
 | 
				
			||||||
			frames = &animation->rootAnimation.frames;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case ANM2_LAYER_ANIMATION:
 | 
					 | 
				
			||||||
			if (id < 0 || id >= (s32)animation->layerAnimations.size())
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			frames = &animation->layerAnimations[id].frames;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case ANM2_NULL_ANIMATION:
 | 
					 | 
				
			||||||
			if (id < 0 || id >= (s32)animation->nullAnimations.size())
 | 
					 | 
				
			||||||
				return false;
 | 
					 | 
				
			||||||
			frames = &animation->nullAnimations[id].frames;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (s32 i = 0; i < (s32)frames->size(); i++)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		*frame = (*frames)[i];
 | 
					 | 
				
			||||||
		delayNext += frame->delay;
 | 
							delayNext += frame->delay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* If a frame is within the time constraints, it's a time matched frame, break */
 | 
							/* If a frame is within the time constraints, it's a time matched frame, break */
 | 
				
			||||||
		/* Otherwise, the last found frame parsed will be used. */
 | 
							/* Otherwise, the last found frame parsed will be used. */
 | 
				
			||||||
		if (time >= delayCurrent && time < delayNext)
 | 
							if (time >= delayCurrent && time < delayNext)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (i + 1 < (s32)frames->size())
 | 
								if (i + 1 < (s32)item->frames.size())
 | 
				
			||||||
				nextFrame = &(*frames)[i + 1];
 | 
									nextFrame = &item->frames[i + 1];
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				nextFrame = NULL;
 | 
									nextFrame = NULL;
 | 
				
			||||||
 | 
					 | 
				
			||||||
			isTimeMatchedFrame = true;
 | 
					 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		delayCurrent += frame->delay;
 | 
							delayCurrent += frame->delay;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* No valid frame found */
 | 
						/* Interpolate only if there's a frame following */
 | 
				
			||||||
	if (!isTimeMatchedFrame)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* interpolate only if there's a frame following */
 | 
					 | 
				
			||||||
	if (frame->isInterpolated && nextFrame)
 | 
						if (frame->isInterpolated && nextFrame)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		f32 interpolationTime = (time - delayCurrent) / (delayNext - delayCurrent);
 | 
							f32 interpolationTime = (time - delayCurrent) / (delayNext - delayCurrent);
 | 
				
			||||||
@@ -830,6 +809,67 @@ anm2_frame_from_time(Anm2* self, Anm2Animation* animation, Anm2Frame* frame, Anm
 | 
				
			|||||||
		frame->offsetRGB   = glm::mix(frame->offsetRGB,   nextFrame->offsetRGB,   interpolationTime);;
 | 
							frame->offsetRGB   = glm::mix(frame->offsetRGB,   nextFrame->offsetRGB,   interpolationTime);;
 | 
				
			||||||
		frame->tintRGBA    = glm::mix(frame->tintRGBA,    nextFrame->tintRGBA,    interpolationTime);;
 | 
							frame->tintRGBA    = glm::mix(frame->tintRGBA,    nextFrame->tintRGBA,    interpolationTime);;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
					/* Will try adding a frame to the anm2 given the specified reference */
 | 
				
			||||||
 | 
					Anm2Frame*
 | 
				
			||||||
 | 
					anm2_frame_add(Anm2* self, Anm2Reference* reference, s32 animationID, s32 time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Anm2Animation* animation = anm2_animation_from_id(self, animationID);
 | 
				
			||||||
 | 
						Anm2Item* item = anm2_item_from_reference(self, reference, animationID);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (!animation || !item)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (item)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Anm2Frame frame = Anm2Frame{};
 | 
				
			||||||
 | 
							s32 index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (reference->type == ANM2_TRIGGERS)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								/* don't add redudant triggers (i.e. at same time) */
 | 
				
			||||||
 | 
								for (auto & frameCheck : item->frames)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if (frameCheck.atFrame == time)
 | 
				
			||||||
 | 
										return NULL;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								frame.atFrame = time;
 | 
				
			||||||
 | 
								index = item->frames.size();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								s32 delay = 0;
 | 
				
			||||||
 | 
								s32 frameDelayCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Add up all delay to see where this new frame might lie */
 | 
				
			||||||
 | 
								for (auto & frameCheck : item->frames)
 | 
				
			||||||
 | 
									frameDelayCount += frameCheck.delay;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								/* If adding the smallest frame would be over the length, don't bother */
 | 
				
			||||||
 | 
								if (frameDelayCount + ANM2_FRAME_DELAY_MIN > animation->frameNum)
 | 
				
			||||||
 | 
									return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Will insert next to frame if frame exists */
 | 
				
			||||||
 | 
								Anm2Frame* checkFrame = anm2_frame_from_reference(self, reference, animationID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (checkFrame)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									/* Will shrink frame delay to fit */
 | 
				
			||||||
 | 
									if (frameDelayCount + checkFrame->delay > animation->frameNum)
 | 
				
			||||||
 | 
										frame.delay = animation->frameNum - frameDelayCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									index = reference->index + 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									index = (s32)item->frames.size();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							item->frames.insert(item->frames.begin() + index, frame);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return &item->frames[index];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										66
									
								
								src/anm2.h
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/anm2.h
									
									
									
									
									
								
							@@ -14,6 +14,7 @@
 | 
				
			|||||||
#define ANM2_FPS_MAX 120
 | 
					#define ANM2_FPS_MAX 120
 | 
				
			||||||
#define ANM2_FRAME_NUM_MIN 1
 | 
					#define ANM2_FRAME_NUM_MIN 1
 | 
				
			||||||
#define ANM2_FRAME_NUM_MAX 1000000
 | 
					#define ANM2_FRAME_NUM_MAX 1000000
 | 
				
			||||||
 | 
					#define ANM2_FRAME_DELAY_MIN 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Elements */
 | 
					/* Elements */
 | 
				
			||||||
#define ANM2_ELEMENT_LIST \
 | 
					#define ANM2_ELEMENT_LIST \
 | 
				
			||||||
@@ -108,14 +109,14 @@ static const char* ANM2_ATTRIBUTE_STRINGS[] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
DEFINE_STRING_TO_ENUM_FN(anm2_attribute_from_string, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT)
 | 
					DEFINE_STRING_TO_ENUM_FN(anm2_attribute_from_string, Anm2Attribute, ANM2_ATTRIBUTE_STRINGS, ANM2_ATTRIBUTE_COUNT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ANM2_ANIMATION_TYPE_COUNT (ANM2_ANIMATION_TRIGGERS + 1)
 | 
					#define ANM2_COUNT (ANM2_TRIGGER + 1)
 | 
				
			||||||
enum Anm2AnimationType
 | 
					enum Anm2Type
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ANM2_NONE,
 | 
					    ANM2_NONE,
 | 
				
			||||||
	ANM2_ROOT_ANIMATION,
 | 
						ANM2_ROOT,
 | 
				
			||||||
	ANM2_LAYER_ANIMATION,
 | 
						ANM2_LAYER,
 | 
				
			||||||
	ANM2_NULL_ANIMATION,
 | 
						ANM2_NULL,
 | 
				
			||||||
    ANM2_TRIGGER
 | 
					    ANM2_TRIGGERS
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Anm2Spritesheet
 | 
					struct Anm2Spritesheet
 | 
				
			||||||
@@ -140,18 +141,14 @@ struct Anm2Event
 | 
				
			|||||||
	char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_EVENT;
 | 
						char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_EVENT;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Anm2Trigger
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	s32 eventID = -1;
 | 
					 | 
				
			||||||
	s32 atFrame = -1;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Anm2Frame
 | 
					struct Anm2Frame
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool isInterpolated = false;
 | 
						bool isInterpolated = false;
 | 
				
			||||||
	bool isVisible = true;
 | 
						bool isVisible = true;
 | 
				
			||||||
	f32 rotation = 1.0f;
 | 
						f32 rotation = 1.0f;
 | 
				
			||||||
	s32 delay = 1;
 | 
						s32 delay = ANM2_FRAME_DELAY_MIN;
 | 
				
			||||||
 | 
					    s32 atFrame = -1;
 | 
				
			||||||
 | 
					    s32 eventID = -1;
 | 
				
			||||||
	vec2 crop = {0.0f, 0.0f};
 | 
						vec2 crop = {0.0f, 0.0f};
 | 
				
			||||||
	vec2 pivot = {0.0f, 0.0f};
 | 
						vec2 pivot = {0.0f, 0.0f};
 | 
				
			||||||
	vec2 position = {0.0f, 0.0f};
 | 
						vec2 position = {0.0f, 0.0f};
 | 
				
			||||||
@@ -161,39 +158,21 @@ struct Anm2Frame
 | 
				
			|||||||
	vec4 tintRGBA = {1.0f, 1.0f, 1.0f, 1.0f};
 | 
						vec4 tintRGBA = {1.0f, 1.0f, 1.0f, 1.0f};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Anm2LayerAnimation
 | 
					struct Anm2Item
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	bool isVisible = true;
 | 
					 | 
				
			||||||
	std::vector<Anm2Frame> frames;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Anm2NullAnimation
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	bool isVisible = true;
 | 
					 | 
				
			||||||
	std::vector<Anm2Frame> frames;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Anm2RootAnimation
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool isVisible = true;
 | 
					    bool isVisible = true;
 | 
				
			||||||
	std::vector<Anm2Frame> frames;
 | 
						std::vector<Anm2Frame> frames;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Anm2Triggers
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    bool isVisible = true;
 | 
					 | 
				
			||||||
    std::vector<Anm2Trigger> items;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct Anm2Animation
 | 
					struct Anm2Animation
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	s32 frameNum = ANM2_FRAME_NUM_MIN;
 | 
						s32 frameNum = ANM2_FRAME_NUM_MIN;
 | 
				
			||||||
	char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_ANIMATION;
 | 
						char name[ANM2_STRING_MAX] = STRING_ANM2_NEW_ANIMATION;
 | 
				
			||||||
	bool isLoop = true;
 | 
						bool isLoop = true;
 | 
				
			||||||
	Anm2RootAnimation rootAnimation;
 | 
					    Anm2Item rootAnimation;
 | 
				
			||||||
    std::map<s32, Anm2LayerAnimation> layerAnimations; 
 | 
					    std::map<s32, Anm2Item> layerAnimations;
 | 
				
			||||||
	std::map<s32, Anm2NullAnimation> nullAnimations;
 | 
					    std::map<s32, Anm2Item> nullAnimations;
 | 
				
			||||||
    Anm2Triggers triggers;
 | 
					    Anm2Item triggers;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Anm2 
 | 
					struct Anm2 
 | 
				
			||||||
@@ -211,6 +190,15 @@ struct Anm2
 | 
				
			|||||||
	std::map<s32, Anm2Animation> animations; 
 | 
						std::map<s32, Anm2Animation> animations; 
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Anm2Reference
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Anm2Type type = ANM2_NONE;
 | 
				
			||||||
 | 
					    s32 id = -1;
 | 
				
			||||||
 | 
					    s32 index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto operator<=>(const Anm2Reference&) const = default; 
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void anm2_layer_add(Anm2* self);
 | 
					void anm2_layer_add(Anm2* self);
 | 
				
			||||||
void anm2_layer_remove(Anm2* self, s32 id);
 | 
					void anm2_layer_remove(Anm2* self, s32 id);
 | 
				
			||||||
void anm2_null_add(Anm2* self);
 | 
					void anm2_null_add(Anm2* self);
 | 
				
			||||||
@@ -222,4 +210,8 @@ void anm2_created_on_set(Anm2* self);
 | 
				
			|||||||
s32 anm2_animation_add(Anm2* self);
 | 
					s32 anm2_animation_add(Anm2* self);
 | 
				
			||||||
void anm2_animation_remove(Anm2* self, s32 id);
 | 
					void anm2_animation_remove(Anm2* self, s32 id);
 | 
				
			||||||
void anm2_spritesheet_texture_load(Anm2* self, Resources* resources, const char* path, s32 id);
 | 
					void anm2_spritesheet_texture_load(Anm2* self, Resources* resources, const char* path, s32 id);
 | 
				
			||||||
bool anm2_frame_from_time(Anm2* self, Anm2Animation* animation, Anm2Frame* frame, Anm2AnimationType type, s32 id, f32 time);
 | 
					Anm2Animation* anm2_animation_from_id(Anm2* self, s32 animationID);
 | 
				
			||||||
 | 
					Anm2Item* anm2_item_from_reference(Anm2* self, Anm2Reference* reference, s32 animationID);
 | 
				
			||||||
 | 
					Anm2Frame* anm2_frame_from_reference(Anm2* self, Anm2Reference* reference, s32 animationID);
 | 
				
			||||||
 | 
					Anm2Frame* anm2_frame_add(Anm2* self, Anm2Reference* reference, s32 animationID, s32 time);
 | 
				
			||||||
 | 
					void anm2_frame_from_time(Anm2* self, Anm2Frame* frame, Anm2Reference reference, s32 animationID, f32 time);
 | 
				
			||||||
@@ -19,9 +19,10 @@ _dialog_callback(void* userdata, const char* const* filelist, s32 filter)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
dialog_init(Dialog* self, Anm2* anm2, Resources* resources, SDL_Window* window)
 | 
					dialog_init(Dialog* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, SDL_Window* window)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	self->anm2 = anm2;
 | 
						self->anm2 = anm2;
 | 
				
			||||||
 | 
						self->reference = reference;
 | 
				
			||||||
	self->resources = resources;
 | 
						self->resources = resources;
 | 
				
			||||||
	self->window = window;
 | 
						self->window = window;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -76,6 +77,7 @@ dialog_tick(Dialog* self)
 | 
				
			|||||||
		switch (self->type)
 | 
							switch (self->type)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			case DIALOG_ANM2_OPEN:
 | 
								case DIALOG_ANM2_OPEN:
 | 
				
			||||||
 | 
									*self->reference = Anm2Reference{};
 | 
				
			||||||
				resources_textures_free(self->resources);
 | 
									resources_textures_free(self->resources);
 | 
				
			||||||
				anm2_deserialize(self->anm2, self->resources, self->path);
 | 
									anm2_deserialize(self->anm2, self->resources, self->path);
 | 
				
			||||||
				window_title_from_anm2_set(self->window, self->anm2);
 | 
									window_title_from_anm2_set(self->window, self->anm2);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,7 @@ enum DialogType
 | 
				
			|||||||
struct Dialog
 | 
					struct Dialog
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Anm2* anm2 = NULL;
 | 
					    Anm2* anm2 = NULL;
 | 
				
			||||||
 | 
					    Anm2Reference* reference = NULL;
 | 
				
			||||||
    Resources* resources = NULL;
 | 
					    Resources* resources = NULL;
 | 
				
			||||||
    SDL_Window* window = NULL;
 | 
					    SDL_Window* window = NULL;
 | 
				
			||||||
    s32 replaceID = -1;
 | 
					    s32 replaceID = -1;
 | 
				
			||||||
@@ -34,7 +35,7 @@ struct Dialog
 | 
				
			|||||||
    bool isSelected = false;
 | 
					    bool isSelected = false;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dialog_init(Dialog* self, Anm2* anm2, Resources* resources, SDL_Window* window);
 | 
					void dialog_init(Dialog* self, Anm2* anm2, Anm2Reference* reference, Resources* resources, SDL_Window* window);
 | 
				
			||||||
void dialog_anm2_open(Dialog* self);
 | 
					void dialog_anm2_open(Dialog* self);
 | 
				
			||||||
void dialog_png_open(Dialog* self);
 | 
					void dialog_png_open(Dialog* self);
 | 
				
			||||||
void dialog_png_replace(Dialog* self);
 | 
					void dialog_png_replace(Dialog* self);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
#include "editor.h"
 | 
					#include "editor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void _editor_grid_set(Editor* self);
 | 
					static s32 _editor_grid_set(Editor* self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static s32
 | 
				
			||||||
_editor_grid_set(Editor* self)
 | 
					_editor_grid_set(Editor* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::vector<f32> vertices;
 | 
					    std::vector<f32> vertices;
 | 
				
			||||||
@@ -34,19 +34,32 @@ _editor_grid_set(Editor* self)
 | 
				
			|||||||
        vertices.push_back(normY);
 | 
					        vertices.push_back(normY);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->gridVertexCount = (s32)vertices.size();
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    glBindVertexArray(self->gridVAO);
 | 
					    glBindVertexArray(self->gridVAO);
 | 
				
			||||||
    glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO);
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO);
 | 
				
			||||||
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(f32), vertices.data(), GL_DYNAMIC_DRAW);
 | 
					    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(f32), vertices.data(), GL_DYNAMIC_DRAW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glEnableVertexAttribArray(0);
 | 
					    glEnableVertexAttribArray(0);
 | 
				
			||||||
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0);
 | 
					    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (s32)vertices.size();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
editor_init(Editor* self, Resources* resources, Settings* settings)
 | 
					editor_init
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
					    Editor* self, 
 | 
				
			||||||
 | 
					    Anm2* anm2, 
 | 
				
			||||||
 | 
					    Anm2Reference* reference, 
 | 
				
			||||||
 | 
					    s32* animationID, 
 | 
				
			||||||
 | 
					    s32* spritesheetID, 
 | 
				
			||||||
 | 
					    Resources* resources, 
 | 
				
			||||||
 | 
					    Settings* settings
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    self->anm2 = anm2;
 | 
				
			||||||
 | 
					    self->reference = reference;
 | 
				
			||||||
 | 
					    self->animationID = animationID;
 | 
				
			||||||
 | 
					    self->spritesheetID = spritesheetID;
 | 
				
			||||||
    self->resources = resources;
 | 
					    self->resources = resources;
 | 
				
			||||||
    self->settings = settings;
 | 
					    self->settings = settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -140,9 +153,9 @@ editor_draw(Editor* self)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    glClear(GL_COLOR_BUFFER_BIT);
 | 
					    glClear(GL_COLOR_BUFFER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (self->spritesheetID > -1)
 | 
					    if (*self->spritesheetID > -1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Texture* texture = &self->resources->textures[self->spritesheetID];
 | 
					        Texture* texture = &self->resources->textures[*self->spritesheetID];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        glm::mat4 spritesheetTransform = editorTransform;
 | 
					        glm::mat4 spritesheetTransform = editorTransform;
 | 
				
			||||||
        glm::vec2 ndcScale = glm::vec2(texture->size.x, texture->size.y) / (EDITOR_SIZE * 0.5f);
 | 
					        glm::vec2 ndcScale = glm::vec2(texture->size.x, texture->size.y) / (EDITOR_SIZE * 0.5f);
 | 
				
			||||||
@@ -186,12 +199,16 @@ editor_draw(Editor* self)
 | 
				
			|||||||
            glUseProgram(0);
 | 
					            glUseProgram(0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (self->isFrame)
 | 
					        Anm2Frame* frame = (Anm2Frame*)anm2_frame_from_reference(self->anm2, self->reference, *self->animationID);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Draw the layer frame's crop and pivot */
 | 
				
			||||||
 | 
					        if (frame && self->reference->type == ANM2_LAYER)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            /* Rect */
 | 
				
			||||||
            glm::mat4 rectTransform = editorTransform;  
 | 
					            glm::mat4 rectTransform = editorTransform;  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            glm::vec2 rectNDCPos = self->frame.crop / (EDITOR_SIZE / 2.0f);  
 | 
					            glm::vec2 rectNDCPos = frame->crop / (EDITOR_SIZE / 2.0f);  
 | 
				
			||||||
            glm::vec2 rectNDCScale = self->frame.size / (EDITOR_SIZE * 0.5f);
 | 
					            glm::vec2 rectNDCScale = frame->size / (EDITOR_SIZE / 2.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            rectTransform = glm::translate(rectTransform, glm::vec3(rectNDCPos, 0.0f));  
 | 
					            rectTransform = glm::translate(rectTransform, glm::vec3(rectNDCPos, 0.0f));  
 | 
				
			||||||
            rectTransform = glm::scale(rectTransform, glm::vec3(rectNDCScale, 1.0f));
 | 
					            rectTransform = glm::scale(rectTransform, glm::vec3(rectNDCScale, 1.0f));
 | 
				
			||||||
@@ -208,9 +225,10 @@ editor_draw(Editor* self)
 | 
				
			|||||||
            glBindVertexArray(0);
 | 
					            glBindVertexArray(0);
 | 
				
			||||||
            glUseProgram(0);
 | 
					            glUseProgram(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Pivot */
 | 
				
			||||||
            glm::mat4 pivotTransform = editorTransform;
 | 
					            glm::mat4 pivotTransform = editorTransform;
 | 
				
			||||||
            glm::vec2 pivotNDCPos = self->frame.pivot / (EDITOR_SIZE / 2.0f);
 | 
					            glm::vec2 pivotNDCPos = ((frame->crop + frame->pivot) - (EDITOR_PIVOT_SIZE / 2.0f)) / (EDITOR_SIZE / 2.0f);
 | 
				
			||||||
            glm::vec2 pivotNDCScale = ATLAS_SIZES[TEXTURE_PIVOT] / (EDITOR_SIZE * 0.5f);
 | 
					            glm::vec2 pivotNDCScale = EDITOR_PIVOT_SIZE / (EDITOR_SIZE / 2.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            pivotTransform = glm::translate(pivotTransform, glm::vec3(pivotNDCPos, 0.0f));
 | 
					            pivotTransform = glm::translate(pivotTransform, glm::vec3(pivotNDCPos, 0.0f));
 | 
				
			||||||
            pivotTransform = glm::scale(pivotTransform, glm::vec3(pivotNDCScale, 1.0f));
 | 
					            pivotTransform = glm::scale(pivotTransform, glm::vec3(pivotNDCScale, 1.0f));
 | 
				
			||||||
@@ -244,16 +262,21 @@ editor_draw(Editor* self)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (self->settings->editorIsGrid)
 | 
					    if (self->settings->editorIsGrid)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if 
 | 
					        static ivec2 previousGridSize = {-1, -1};
 | 
				
			||||||
        (
 | 
					        static ivec2 previousGridOffset = {-1, -1};
 | 
				
			||||||
            (ivec2(self->settings->editorGridSizeX, self->settings->editorGridSizeY) != self->oldGridSize) ||
 | 
					        static s32 gridVertexCount = -1;
 | 
				
			||||||
            (ivec2(self->settings->editorGridOffsetX, self->settings->editorGridOffsetY) != self->oldGridOffset)
 | 
					        ivec2 gridSize = ivec2(self->settings->editorGridSizeX, self->settings->editorGridSizeY);
 | 
				
			||||||
        )
 | 
					        ivec2 gridOffset = ivec2(self->settings->editorGridOffsetX, self->settings->editorGridOffsetY);
 | 
				
			||||||
            _editor_grid_set(self);
 | 
					
 | 
				
			||||||
 | 
					        if (previousGridSize != gridSize || previousGridOffset != gridOffset)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            gridVertexCount = _editor_grid_set(self);
 | 
				
			||||||
 | 
					            previousGridSize = gridSize;
 | 
				
			||||||
 | 
					            previousGridOffset = gridOffset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        glUseProgram(shaderLine);
 | 
					        glUseProgram(shaderLine);
 | 
				
			||||||
        glBindVertexArray(self->gridVAO);
 | 
					        glBindVertexArray(self->gridVAO);
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
        glUniformMatrix4fv(glGetUniformLocation(shaderLine, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, (f32*)value_ptr(editorTransform));
 | 
					        glUniformMatrix4fv(glGetUniformLocation(shaderLine, SHADER_UNIFORM_TRANSFORM), 1, GL_FALSE, (f32*)value_ptr(editorTransform));
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        glUniform4f
 | 
					        glUniform4f
 | 
				
			||||||
@@ -262,7 +285,7 @@ editor_draw(Editor* self)
 | 
				
			|||||||
            self->settings->editorGridColorR, self->settings->editorGridColorG, self->settings->editorGridColorB, self->settings->editorGridColorA
 | 
					            self->settings->editorGridColorR, self->settings->editorGridColorG, self->settings->editorGridColorB, self->settings->editorGridColorA
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        glDrawArrays(GL_LINES, 0, self->gridVertexCount);
 | 
					        glDrawArrays(GL_LINES, 0, gridVertexCount);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        glBindVertexArray(0);
 | 
					        glBindVertexArray(0);
 | 
				
			||||||
        glUseProgram(0);
 | 
					        glUseProgram(0);
 | 
				
			||||||
@@ -275,8 +298,6 @@ void
 | 
				
			|||||||
editor_tick(Editor* self)
 | 
					editor_tick(Editor* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    self->settings->editorZoom = CLAMP(self->settings->editorZoom, EDITOR_ZOOM_MIN, EDITOR_ZOOM_MAX);
 | 
					    self->settings->editorZoom = CLAMP(self->settings->editorZoom, EDITOR_ZOOM_MIN, EDITOR_ZOOM_MAX);
 | 
				
			||||||
    self->oldGridSize = glm::vec2(self->settings->editorGridSizeX, self->settings->editorGridSizeY);
 | 
					 | 
				
			||||||
    self->oldGridOffset = glm::vec2(self->settings->editorGridOffsetX, self->settings->editorGridOffsetY);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								src/editor.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/editor.h
									
									
									
									
									
								
							@@ -13,12 +13,17 @@
 | 
				
			|||||||
#define EDITOR_GRID_OFFSET_MAX 100
 | 
					#define EDITOR_GRID_OFFSET_MAX 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const vec2 EDITOR_SIZE = {5000, 5000};
 | 
					static const vec2 EDITOR_SIZE = {5000, 5000};
 | 
				
			||||||
 | 
					static const vec2 EDITOR_PIVOT_SIZE = {4, 4};
 | 
				
			||||||
static const vec4 EDITOR_TEXTURE_TINT = COLOR_OPAQUE;
 | 
					static const vec4 EDITOR_TEXTURE_TINT = COLOR_OPAQUE;
 | 
				
			||||||
static const vec4 EDITOR_BORDER_TINT = COLOR_OPAQUE;
 | 
					static const vec4 EDITOR_BORDER_TINT = COLOR_OPAQUE;
 | 
				
			||||||
static const vec4 EDITOR_FRAME_TINT = COLOR_RED;
 | 
					static const vec4 EDITOR_FRAME_TINT = COLOR_RED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Editor
 | 
					struct Editor
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Anm2* anm2 = NULL;
 | 
				
			||||||
 | 
					    Anm2Reference* reference = NULL;
 | 
				
			||||||
 | 
					    s32* animationID = NULL;
 | 
				
			||||||
 | 
					    s32* spritesheetID = NULL;
 | 
				
			||||||
    Resources* resources = NULL;
 | 
					    Resources* resources = NULL;
 | 
				
			||||||
    Settings* settings = NULL;
 | 
					    Settings* settings = NULL;
 | 
				
			||||||
    GLuint fbo;
 | 
					    GLuint fbo;
 | 
				
			||||||
@@ -31,16 +36,19 @@ struct Editor
 | 
				
			|||||||
    GLuint textureVBO;
 | 
					    GLuint textureVBO;
 | 
				
			||||||
    GLuint borderVAO;
 | 
					    GLuint borderVAO;
 | 
				
			||||||
    GLuint borderVBO;
 | 
					    GLuint borderVBO;
 | 
				
			||||||
    s32 gridVertexCount = -1;
 | 
					 | 
				
			||||||
    s32 spritesheetID = -1;
 | 
					 | 
				
			||||||
    s32 oldSpritesheetID = -1;
 | 
					 | 
				
			||||||
    ivec2 oldGridSize = {-1, -1};
 | 
					 | 
				
			||||||
    ivec2 oldGridOffset = {-1, -1};
 | 
					 | 
				
			||||||
    Anm2Frame frame;
 | 
					 | 
				
			||||||
    bool isFrame = false;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void editor_init(Editor* self, Resources* resources, Settings* settings);
 | 
					void editor_init
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
					    Editor* self, 
 | 
				
			||||||
 | 
					    Anm2* anm2, 
 | 
				
			||||||
 | 
					    Anm2Reference* reference, 
 | 
				
			||||||
 | 
					    s32* animationID, 
 | 
				
			||||||
 | 
					    s32* spritesheetID, 
 | 
				
			||||||
 | 
					    Resources* resources, 
 | 
				
			||||||
 | 
					    Settings* settings
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void editor_draw(Editor* self);
 | 
					void editor_draw(Editor* self);
 | 
				
			||||||
void editor_tick(Editor* self);
 | 
					void editor_tick(Editor* self);
 | 
				
			||||||
void editor_free(Editor* self);
 | 
					void editor_free(Editor* self);
 | 
				
			||||||
							
								
								
									
										1467
									
								
								src/imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										1467
									
								
								src/imgui.cpp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										52
									
								
								src/imgui.h
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								src/imgui.h
									
									
									
									
									
								
							@@ -7,6 +7,7 @@
 | 
				
			|||||||
#include "window.h"
 | 
					#include "window.h"
 | 
				
			||||||
#include "input.h"
 | 
					#include "input.h"
 | 
				
			||||||
#include "settings.h"
 | 
					#include "settings.h"
 | 
				
			||||||
 | 
					#include "tool.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM
 | 
					#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM
 | 
				
			||||||
#define IMGUI_ENABLE_DOCKING
 | 
					#define IMGUI_ENABLE_DOCKING
 | 
				
			||||||
@@ -15,8 +16,6 @@
 | 
				
			|||||||
#include <imgui/backends/imgui_impl_sdl3.h>
 | 
					#include <imgui/backends/imgui_impl_sdl3.h>
 | 
				
			||||||
#include <imgui/backends/imgui_impl_opengl3.h>
 | 
					#include <imgui/backends/imgui_impl_opengl3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#define IMGUI_TIMELINE_ELEMENT_WIDTH 300
 | 
					 | 
				
			||||||
#define IMGUI_TIMELINE_ELEMENT_WIDTH 300
 | 
					#define IMGUI_TIMELINE_ELEMENT_WIDTH 300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IMGUI_DRAG_SPEED 1.0
 | 
					#define IMGUI_DRAG_SPEED 1.0
 | 
				
			||||||
@@ -32,15 +31,15 @@
 | 
				
			|||||||
#define IMGUI_PICKER_LINE_COLOR IM_COL32(255, 255, 255, 255)
 | 
					#define IMGUI_PICKER_LINE_COLOR IM_COL32(255, 255, 255, 255)
 | 
				
			||||||
#define IMGUI_TOOLS_WIDTH_INCREMENT -2
 | 
					#define IMGUI_TOOLS_WIDTH_INCREMENT -2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IMGUI_POSITION_STRING_MAX 0xFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const vec2 IMGUI_TASKBAR_MARGINS = {8, 4};
 | 
					static const vec2 IMGUI_TASKBAR_MARGINS = {8, 4};
 | 
				
			||||||
 | 
					static const vec2 IMGUI_SPRITESHEET_EDITOR_CROP_FORGIVENESS = {1, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_SIZE = {1280, 105};
 | 
					static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_SIZE = {1280, 105};
 | 
				
			||||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_CHILD_SIZE = {200, 85};
 | 
					static const ImVec2 IMGUI_ANIMATION_PREVIEW_SETTINGS_CHILD_SIZE = {200, 85};
 | 
				
			||||||
static const ImVec2 IMGUI_ANIMATION_PREVIEW_POSITION = {8, 135};
 | 
					static const ImVec2 IMGUI_ANIMATION_PREVIEW_POSITION = {8, 135};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_NAME_SIZE = {95, 20};
 | 
					 | 
				
			||||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_SIZE = {45, 20};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_CHILD_SIZE = {200, 85};
 | 
					static const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_CHILD_SIZE = {200, 85};
 | 
				
			||||||
static const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_SIZE = {1280, 105};
 | 
					static const ImVec2 IMGUI_SPRITESHEET_EDITOR_SETTINGS_SIZE = {1280, 105};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,15 +51,13 @@ static const ImVec2 IMGUI_TIMELINE_VIEWER_SIZE = {0, 40};
 | 
				
			|||||||
static const ImVec2 IMGUI_TIMELINE_ELEMENTS_TIMELINE_SIZE = {0, 40};
 | 
					static const ImVec2 IMGUI_TIMELINE_ELEMENTS_TIMELINE_SIZE = {0, 40};
 | 
				
			||||||
static const ImVec2 IMGUI_TIMELINE_FRAME_INDICES_SIZE = {0, 40};
 | 
					static const ImVec2 IMGUI_TIMELINE_FRAME_INDICES_SIZE = {0, 40};
 | 
				
			||||||
static const ImVec2 IMGUI_TIMELINE_ELEMENT_SIZE = {300, 40};
 | 
					static const ImVec2 IMGUI_TIMELINE_ELEMENT_SIZE = {300, 40};
 | 
				
			||||||
static const ImVec2 IMGUI_TIMELINE_SHIFT_ARROWS_SIZE = {64, 40};
 | 
					static const ImVec2 IMGUI_TIMELINE_ELEMENT_NAME_SIZE = {150, 20};
 | 
				
			||||||
 | 
					static const ImVec2 IMGUI_TIMELINE_ELEMENT_SPRITESHEET_ID_SIZE = {60, 20};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const ImVec2 IMGUI_SPRITESHEET_SIZE = {0, 150};
 | 
					static const ImVec2 IMGUI_SPRITESHEET_SIZE = {0, 150};
 | 
				
			||||||
static const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {100, 100};
 | 
					static const ImVec2 IMGUI_SPRITESHEET_PREVIEW_SIZE = {100, 100};
 | 
				
			||||||
static const ImVec2 IMGUI_ICON_SIZE = {16, 16};
 | 
					 | 
				
			||||||
static const ImVec2 IMGUI_ICON_SMALL_SIZE = {8, 8};
 | 
					 | 
				
			||||||
static const ImVec2 IMGUI_ICON_DUMMY_SIZE = {20, 16};
 | 
					 | 
				
			||||||
static const ImVec2 IMGUI_ICON_BUTTON_SIZE = {24, 24};
 | 
					 | 
				
			||||||
static const ImVec2 IMGUI_IMAGE_TARGET_SIZE = {125, 125};
 | 
					static const ImVec2 IMGUI_IMAGE_TARGET_SIZE = {125, 125};
 | 
				
			||||||
 | 
					static const ImVec2 IMGUI_ICON_BUTTON_SIZE = {24, 24};
 | 
				
			||||||
static const ImVec2 IMGUI_DUMMY_SIZE = {1, 1};
 | 
					static const ImVec2 IMGUI_DUMMY_SIZE = {1, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const ImVec4 IMGUI_TIMELINE_HEADER_COLOR = {0.04, 0.04, 0.04, 1.0f};
 | 
					static const ImVec4 IMGUI_TIMELINE_HEADER_COLOR = {0.04, 0.04, 0.04, 1.0f};
 | 
				
			||||||
@@ -89,15 +86,6 @@ static const ImVec4 IMGUI_TIMELINE_LAYER_ACTIVE_COLOR = {1.000, 0.618, 0.324, 0.
 | 
				
			|||||||
static const ImVec4 IMGUI_TIMELINE_NULL_ACTIVE_COLOR = {0.646, 0.971, 0.441, 0.75};
 | 
					static const ImVec4 IMGUI_TIMELINE_NULL_ACTIVE_COLOR = {0.646, 0.971, 0.441, 0.75};
 | 
				
			||||||
static const ImVec4 IMGUI_TIMELINE_TRIGGERS_ACTIVE_COLOR = {1.000, 0.618, 0.735, 0.75};
 | 
					static const ImVec4 IMGUI_TIMELINE_TRIGGERS_ACTIVE_COLOR = {1.000, 0.618, 0.735, 0.75};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TOOL_COUNT (TOOL_CROP + 1)
 | 
					 | 
				
			||||||
enum ToolType
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    TOOL_PAN,
 | 
					 | 
				
			||||||
    TOOL_MOVE,
 | 
					 | 
				
			||||||
    TOOL_ROTATE,
 | 
					 | 
				
			||||||
    TOOL_SCALE,
 | 
					 | 
				
			||||||
    TOOL_CROP
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Imgui
 | 
					struct Imgui
 | 
				
			||||||
{  
 | 
					{  
 | 
				
			||||||
@@ -105,36 +93,38 @@ struct Imgui
 | 
				
			|||||||
    Resources* resources = NULL;
 | 
					    Resources* resources = NULL;
 | 
				
			||||||
    Input* input = NULL;
 | 
					    Input* input = NULL;
 | 
				
			||||||
    Anm2* anm2 = NULL;
 | 
					    Anm2* anm2 = NULL;
 | 
				
			||||||
 | 
					    Anm2Reference* reference = NULL;
 | 
				
			||||||
 | 
					    s32* animationID = NULL;
 | 
				
			||||||
 | 
					    s32* spritesheetID = NULL;
 | 
				
			||||||
    Editor* editor = NULL;
 | 
					    Editor* editor = NULL;
 | 
				
			||||||
    Preview* preview = NULL;
 | 
					    Preview* preview = NULL;
 | 
				
			||||||
 | 
					    Settings* settings = NULL;
 | 
				
			||||||
 | 
					    Tool* tool = NULL;
 | 
				
			||||||
    SDL_Window* window = NULL;
 | 
					    SDL_Window* window = NULL;
 | 
				
			||||||
    SDL_GLContext* glContext = NULL;
 | 
					    SDL_GLContext* glContext = NULL;
 | 
				
			||||||
    Settings* settings = NULL;
 | 
					    bool isSwap = false;
 | 
				
			||||||
    s32 animationID = -1;
 | 
					    Anm2Reference swapReference;
 | 
				
			||||||
    s32 timelineElementID = -1;
 | 
					 | 
				
			||||||
    s32 eventID = -1;
 | 
					 | 
				
			||||||
    s32 spritesheetID = -1;
 | 
					 | 
				
			||||||
    s32 timelineElementIndex = -1;
 | 
					 | 
				
			||||||
    Anm2AnimationType animationType = ANM2_NONE;
 | 
					 | 
				
			||||||
    ToolType tool = TOOL_PAN;
 | 
					 | 
				
			||||||
    void* frameVector = NULL;
 | 
					 | 
				
			||||||
    s32 frameIndex = -1;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void imgui_init
 | 
					void 
 | 
				
			||||||
 | 
					imgui_init
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
    Imgui* self,
 | 
					    Imgui* self,
 | 
				
			||||||
    Dialog* dialog,
 | 
					    Dialog* dialog,
 | 
				
			||||||
    Resources* resources,
 | 
					    Resources* resources,
 | 
				
			||||||
    Input* input,
 | 
					    Input* input,
 | 
				
			||||||
    Anm2* anm2,
 | 
					    Anm2* anm2,
 | 
				
			||||||
 | 
					    Anm2Reference* reference,
 | 
				
			||||||
 | 
					    s32* animationID,
 | 
				
			||||||
 | 
					    s32* spritesheetID,
 | 
				
			||||||
    Editor* editor,
 | 
					    Editor* editor,
 | 
				
			||||||
    Preview* preview,
 | 
					    Preview* preview,
 | 
				
			||||||
    Settings* settings,
 | 
					    Settings* settings,
 | 
				
			||||||
 | 
					    Tool* tool,
 | 
				
			||||||
    SDL_Window* window,
 | 
					    SDL_Window* window,
 | 
				
			||||||
    SDL_GLContext* glContext
 | 
					    SDL_GLContext* glContext
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void imgui_tick(Imgui* self);
 | 
					void imgui_tick(Imgui* self);
 | 
				
			||||||
void imgui_draw(Imgui* self);
 | 
					void imgui_draw(Imgui* self);
 | 
				
			||||||
void imgui_free(Imgui* self);
 | 
					void imgui_free(Imgui* self);
 | 
				
			||||||
@@ -29,6 +29,19 @@ _mouse_tick(Mouse* self)
 | 
				
			|||||||
    self->oldPosition = self->position;
 | 
					    self->oldPosition = self->position;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					_keyboard_tick(Keyboard* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const bool* state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(&self->previous, &self->current, sizeof(self->previous));
 | 
				
			||||||
 | 
						memset(&self->current, '\0', sizeof(self->current));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state = SDL_GetKeyboardState(NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(&self->current, state, KEY_COUNT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool
 | 
					bool
 | 
				
			||||||
mouse_press(Mouse* self, MouseType type)
 | 
					mouse_press(Mouse* self, MouseType type)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -47,8 +60,27 @@ mouse_release(Mouse* self, MouseType type)
 | 
				
			|||||||
    return (!self->current[type] && self->previous[type]);
 | 
					    return (!self->current[type] && self->previous[type]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool
 | 
				
			||||||
 | 
					key_press(Keyboard* self, KeyType type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (self->current[type] && !self->previous[type]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool
 | 
				
			||||||
 | 
					key_held(Keyboard* self, KeyType type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (self->current[type] && self->previous[type]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool
 | 
				
			||||||
 | 
					key_release(Keyboard* self, KeyType type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (!self->current[type] && self->previous[type]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
input_tick(Input* self)
 | 
					input_tick(Input* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _mouse_tick(&self->mouse);
 | 
					    _mouse_tick(&self->mouse);
 | 
				
			||||||
 | 
					    _keyboard_tick(&self->keyboard);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										262
									
								
								src/input.h
									
									
									
									
									
								
							
							
						
						
									
										262
									
								
								src/input.h
									
									
									
									
									
								
							@@ -9,22 +9,267 @@ enum MouseType
 | 
				
			|||||||
    MOUSE_RIGHT
 | 
					    MOUSE_RIGHT
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define KEY_COUNT (KEY_DELETE + 1) 
 | 
					#define KEY_COUNT (255)
 | 
				
			||||||
enum KeyType
 | 
					enum KeyType
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    KEY_DELETE
 | 
					        KEY_UNKNOWN = 0,
 | 
				
			||||||
 | 
					        KEY_UNKNOWN_TWO = 1,
 | 
				
			||||||
 | 
					        KEY_UNKNOWN_THREE = 2,
 | 
				
			||||||
 | 
					        KEY_UNKNOWN_FOUR = 3,
 | 
				
			||||||
 | 
					        KEY_A = 4,
 | 
				
			||||||
 | 
					        KEY_B = 5,
 | 
				
			||||||
 | 
					        KEY_C = 6,
 | 
				
			||||||
 | 
					        KEY_D = 7,
 | 
				
			||||||
 | 
					        KEY_E = 8,
 | 
				
			||||||
 | 
					        KEY_F = 9,
 | 
				
			||||||
 | 
					        KEY_G = 10,
 | 
				
			||||||
 | 
					        KEY_H = 11,
 | 
				
			||||||
 | 
					        KEY_I = 12,
 | 
				
			||||||
 | 
					        KEY_J = 13,
 | 
				
			||||||
 | 
					        KEY_K = 14,
 | 
				
			||||||
 | 
					        KEY_L = 15,
 | 
				
			||||||
 | 
					        KEY_M = 16,
 | 
				
			||||||
 | 
					        KEY_N = 17,
 | 
				
			||||||
 | 
					        KEY_O = 18,
 | 
				
			||||||
 | 
					        KEY_P = 19,
 | 
				
			||||||
 | 
					        KEY_Q = 20,
 | 
				
			||||||
 | 
					        KEY_R = 21,
 | 
				
			||||||
 | 
					        KEY_S = 22,
 | 
				
			||||||
 | 
					        KEY_T = 23,
 | 
				
			||||||
 | 
					        KEY_U = 24,
 | 
				
			||||||
 | 
					        KEY_V = 25,
 | 
				
			||||||
 | 
					        KEY_W = 26,
 | 
				
			||||||
 | 
					        KEY_X = 27,
 | 
				
			||||||
 | 
					        KEY_Y = 28,
 | 
				
			||||||
 | 
					        KEY_Z = 29,
 | 
				
			||||||
 | 
					        KEY_1 = 30,
 | 
				
			||||||
 | 
					        KEY_2 = 31,
 | 
				
			||||||
 | 
					        KEY_3 = 32,
 | 
				
			||||||
 | 
					        KEY_4 = 33,
 | 
				
			||||||
 | 
					        KEY_5 = 34,
 | 
				
			||||||
 | 
					        KEY_6 = 35,
 | 
				
			||||||
 | 
					        KEY_7 = 36,
 | 
				
			||||||
 | 
					        KEY_8 = 37,
 | 
				
			||||||
 | 
					        KEY_9 = 38,
 | 
				
			||||||
 | 
					        KEY_0 = 39,
 | 
				
			||||||
 | 
					        KEY_RETURN = 40,
 | 
				
			||||||
 | 
					        KEY_ESCAPE = 41,
 | 
				
			||||||
 | 
					        KEY_BACKSPACE = 42,
 | 
				
			||||||
 | 
					        KEY_TAB = 43,
 | 
				
			||||||
 | 
					        KEY_SPACE = 44,
 | 
				
			||||||
 | 
					        KEY_MINUS = 45,
 | 
				
			||||||
 | 
					        KEY_EQUALS = 46,
 | 
				
			||||||
 | 
					        KEY_LEFTBRACKET = 47,
 | 
				
			||||||
 | 
					        KEY_RIGHTBRACKET = 48,
 | 
				
			||||||
 | 
					        KEY_BACKSLASH = 49,
 | 
				
			||||||
 | 
					        KEY_NONUSHASH = 50,
 | 
				
			||||||
 | 
					        KEY_SEMICOLON = 51,
 | 
				
			||||||
 | 
					        KEY_APOSTROPHE = 52,
 | 
				
			||||||
 | 
					        KEY_GRAVE = 53,
 | 
				
			||||||
 | 
					        KEY_COMMA = 54,
 | 
				
			||||||
 | 
					        KEY_PERIOD = 55,
 | 
				
			||||||
 | 
					        KEY_SLASH = 56,
 | 
				
			||||||
 | 
					        KEY_CAPSLOCK = 57,
 | 
				
			||||||
 | 
					        KEY_F1 = 58,
 | 
				
			||||||
 | 
					        KEY_F2 = 59,
 | 
				
			||||||
 | 
					        KEY_F3 = 60,
 | 
				
			||||||
 | 
					        KEY_F4 = 61,
 | 
				
			||||||
 | 
					        KEY_F5 = 62,
 | 
				
			||||||
 | 
					        KEY_F6 = 63,
 | 
				
			||||||
 | 
					        KEY_F7 = 64,
 | 
				
			||||||
 | 
					        KEY_F8 = 65,
 | 
				
			||||||
 | 
					        KEY_F9 = 66,
 | 
				
			||||||
 | 
					        KEY_F10 = 67,
 | 
				
			||||||
 | 
					        KEY_F11 = 68,
 | 
				
			||||||
 | 
					        KEY_F12 = 69,
 | 
				
			||||||
 | 
					        KEY_PRINTSCREEN = 70,
 | 
				
			||||||
 | 
					        KEY_SCROLLLOCK = 71,
 | 
				
			||||||
 | 
					        KEY_PAUSE = 72,
 | 
				
			||||||
 | 
					        KEY_INSERT = 73,
 | 
				
			||||||
 | 
					        KEY_HOME = 74,
 | 
				
			||||||
 | 
					        KEY_PAGEUP = 75,
 | 
				
			||||||
 | 
					        KEY_DELETE = 76,
 | 
				
			||||||
 | 
					        KEY_END = 77,
 | 
				
			||||||
 | 
					        KEY_PAGEDOWN = 78,
 | 
				
			||||||
 | 
					        KEY_RIGHT = 79,
 | 
				
			||||||
 | 
					        KEY_LEFT = 80,
 | 
				
			||||||
 | 
					        KEY_DOWN = 81,
 | 
				
			||||||
 | 
					        KEY_UP = 82,
 | 
				
			||||||
 | 
					        KEY_NUMLOCKCLEAR = 83,
 | 
				
			||||||
 | 
					        KEY_KP_DIVIDE = 84,
 | 
				
			||||||
 | 
					        KEY_KP_MULTIPLY = 85,
 | 
				
			||||||
 | 
					        KEY_KP_MINUS = 86,
 | 
				
			||||||
 | 
					        KEY_KP_PLUS = 87,
 | 
				
			||||||
 | 
					        KEY_KP_ENTER = 88,
 | 
				
			||||||
 | 
					        KEY_KP_1 = 89,
 | 
				
			||||||
 | 
					        KEY_KP_2 = 90,
 | 
				
			||||||
 | 
					        KEY_KP_3 = 91,
 | 
				
			||||||
 | 
					        KEY_KP_4 = 92,
 | 
				
			||||||
 | 
					        KEY_KP_5 = 93,
 | 
				
			||||||
 | 
					        KEY_KP_6 = 94,
 | 
				
			||||||
 | 
					        KEY_KP_7 = 95,
 | 
				
			||||||
 | 
					        KEY_KP_8 = 96,
 | 
				
			||||||
 | 
					        KEY_KP_9 = 97,
 | 
				
			||||||
 | 
					        KEY_KP_0 = 98,
 | 
				
			||||||
 | 
					        KEY_KP_PERIOD = 99,
 | 
				
			||||||
 | 
					        KEY_NONUSBACKSLASH = 100,
 | 
				
			||||||
 | 
					        KEY_APPLICATION = 101,
 | 
				
			||||||
 | 
					        KEY_POWER = 102,
 | 
				
			||||||
 | 
					        KEY_KP_EQUALS = 103,
 | 
				
			||||||
 | 
					        KEY_F13 = 104,
 | 
				
			||||||
 | 
					        KEY_F14 = 105,
 | 
				
			||||||
 | 
					        KEY_F15 = 106,
 | 
				
			||||||
 | 
					        KEY_F16 = 107,
 | 
				
			||||||
 | 
					        KEY_F17 = 108,
 | 
				
			||||||
 | 
					        KEY_F18 = 109,
 | 
				
			||||||
 | 
					        KEY_F19 = 110,
 | 
				
			||||||
 | 
					        KEY_F20 = 111,
 | 
				
			||||||
 | 
					        KEY_F21 = 112,
 | 
				
			||||||
 | 
					        KEY_F22 = 113,
 | 
				
			||||||
 | 
					        KEY_F23 = 114,
 | 
				
			||||||
 | 
					        KEY_F24 = 115,
 | 
				
			||||||
 | 
					        KEY_EXECUTE = 116,
 | 
				
			||||||
 | 
					        KEY_HELP = 117,
 | 
				
			||||||
 | 
					        KEY_MENU = 118,
 | 
				
			||||||
 | 
					        KEY_SELECT = 119,
 | 
				
			||||||
 | 
					        KEY_STOP = 120,
 | 
				
			||||||
 | 
					        KEY_AGAIN = 121,
 | 
				
			||||||
 | 
					        KEY_UNDO = 122,
 | 
				
			||||||
 | 
					        KEY_CUT = 123,
 | 
				
			||||||
 | 
					        KEY_COPY = 124,
 | 
				
			||||||
 | 
					        KEY_PASTE = 125,
 | 
				
			||||||
 | 
					        KEY_FIND = 126,
 | 
				
			||||||
 | 
					        KEY_MUTE = 127,
 | 
				
			||||||
 | 
					        KEY_VOLUMEUP = 128,
 | 
				
			||||||
 | 
					        KEY_VOLUMEDOWN = 129,
 | 
				
			||||||
 | 
					        KEY_LOCKINGCAPSLOCK = 130,
 | 
				
			||||||
 | 
					        KEY_LOCKINGNUMLOCK = 131,
 | 
				
			||||||
 | 
					        KEY_LOCKINGSCROLLLOCK = 132,
 | 
				
			||||||
 | 
					        KEY_KP_COMMA = 133,
 | 
				
			||||||
 | 
					        KEY_KP_EQUALSAS400 = 134,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL1 = 135,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL2 = 136,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL3 = 137,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL4 = 138,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL5 = 139,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL6 = 140,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL7 = 141,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL8 = 142,
 | 
				
			||||||
 | 
					        KEY_INTERNATIONAL9 = 143,
 | 
				
			||||||
 | 
					        KEY_LANG1 = 144,
 | 
				
			||||||
 | 
					        KEY_LANG2 = 145,
 | 
				
			||||||
 | 
					        KEY_LANG3 = 146,
 | 
				
			||||||
 | 
					        KEY_LANG4 = 147,
 | 
				
			||||||
 | 
					        KEY_LANG5 = 148,
 | 
				
			||||||
 | 
					        KEY_LANG6 = 149,
 | 
				
			||||||
 | 
					        KEY_LANG7 = 150,
 | 
				
			||||||
 | 
					        KEY_LANG8 = 151,
 | 
				
			||||||
 | 
					        KEY_LANG9 = 152,
 | 
				
			||||||
 | 
					        KEY_ALTERASE = 153,
 | 
				
			||||||
 | 
					        KEY_SYSREQ = 154,
 | 
				
			||||||
 | 
					        KEY_CANCEL = 155,
 | 
				
			||||||
 | 
					        KEY_CLEAR = 156,
 | 
				
			||||||
 | 
					        KEY_PRIOR = 157,
 | 
				
			||||||
 | 
					        KEY_RETURN2 = 158,
 | 
				
			||||||
 | 
					        KEY_SEPARATOR = 159,
 | 
				
			||||||
 | 
					        KEY_OUT = 160,
 | 
				
			||||||
 | 
					        KEY_OPER = 161,
 | 
				
			||||||
 | 
					        KEY_CLEARAGAIN = 162,
 | 
				
			||||||
 | 
					        KEY_CRSEL = 163,
 | 
				
			||||||
 | 
					        KEY_EXSEL = 164,
 | 
				
			||||||
 | 
					        KEY_KP_00 = 176,
 | 
				
			||||||
 | 
					        KEY_KP_000 = 177,
 | 
				
			||||||
 | 
					        KEY_THOUSANDSSEPARATOR = 178,
 | 
				
			||||||
 | 
					        KEY_DECIMALSEPARATOR = 179,
 | 
				
			||||||
 | 
					        KEY_CURRENCYUNIT = 180,
 | 
				
			||||||
 | 
					        KEY_CURRENCYSUBUNIT = 181,
 | 
				
			||||||
 | 
					        KEY_KP_LEFTPAREN = 182,
 | 
				
			||||||
 | 
					        KEY_KP_RIGHTPAREN = 183,
 | 
				
			||||||
 | 
					        KEY_KP_LEFTBRACE = 184,
 | 
				
			||||||
 | 
					        KEY_KP_RIGHTBRACE = 185,
 | 
				
			||||||
 | 
					        KEY_KP_TAB = 186,
 | 
				
			||||||
 | 
					        KEY_KP_BACKSPACE = 187,
 | 
				
			||||||
 | 
					        KEY_KP_A = 188,
 | 
				
			||||||
 | 
					        KEY_KP_B = 189,
 | 
				
			||||||
 | 
					        KEY_KP_C = 190,
 | 
				
			||||||
 | 
					        KEY_KP_D = 191,
 | 
				
			||||||
 | 
					        KEY_KP_E = 192,
 | 
				
			||||||
 | 
					        KEY_KP_F = 193,
 | 
				
			||||||
 | 
					        KEY_KP_XOR = 194,
 | 
				
			||||||
 | 
					        KEY_KP_POWER = 195,
 | 
				
			||||||
 | 
					        KEY_KP_PERCENT = 196,
 | 
				
			||||||
 | 
					        KEY_KP_LESS = 197,
 | 
				
			||||||
 | 
					        KEY_KP_GREATER = 198,
 | 
				
			||||||
 | 
					        KEY_KP_AMPERSAND = 199,
 | 
				
			||||||
 | 
					        KEY_KP_DBLAMPERSAND = 200,
 | 
				
			||||||
 | 
					        KEY_KP_VERTICALBAR = 201,
 | 
				
			||||||
 | 
					        KEY_KP_DBLVERTICALBAR = 202,
 | 
				
			||||||
 | 
					        KEY_KP_COLON = 203,
 | 
				
			||||||
 | 
					        KEY_KP_HASH = 204,
 | 
				
			||||||
 | 
					        KEY_KP_SPACE = 205,
 | 
				
			||||||
 | 
					        KEY_KP_AT = 206,
 | 
				
			||||||
 | 
					        KEY_KP_EXCLAM = 207,
 | 
				
			||||||
 | 
					        KEY_KP_MEMSTORE = 208,
 | 
				
			||||||
 | 
					        KEY_KP_MEMRECALL = 209,
 | 
				
			||||||
 | 
					        KEY_KP_MEMCLEAR = 210,
 | 
				
			||||||
 | 
					        KEY_KP_MEMADD = 211,
 | 
				
			||||||
 | 
					        KEY_KP_MEMSUBTRACT = 212,
 | 
				
			||||||
 | 
					        KEY_KP_MEMMULTIPLY = 213,
 | 
				
			||||||
 | 
					        KEY_KP_MEMDIVIDE = 214,
 | 
				
			||||||
 | 
					        KEY_KP_PLUSMINUS = 215,
 | 
				
			||||||
 | 
					        KEY_KP_CLEAR = 216,
 | 
				
			||||||
 | 
					        KEY_KP_CLEARENTRY = 217,
 | 
				
			||||||
 | 
					        KEY_KP_BINARY = 218,
 | 
				
			||||||
 | 
					        KEY_KP_OCTAL = 219,
 | 
				
			||||||
 | 
					        KEY_KP_DECIMAL = 220,
 | 
				
			||||||
 | 
					        KEY_KP_HEXADECIMAL = 221,
 | 
				
			||||||
 | 
					        KEY_LCTRL = 224,
 | 
				
			||||||
 | 
					        KEY_LSHIFT = 225,
 | 
				
			||||||
 | 
					        KEY_LALT = 226,
 | 
				
			||||||
 | 
					        KEY_LGUI = 227,
 | 
				
			||||||
 | 
					        KEY_RCTRL = 228,
 | 
				
			||||||
 | 
					        KEY_RSHIFT = 229,
 | 
				
			||||||
 | 
					        KEY_RALT = 230,
 | 
				
			||||||
 | 
					        KEY_RGUI = 231
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define INPUT_COUNT (INPUT_MOUSE_CLICK + 1)
 | 
					#define INPUT_COUNT (INPUT_ZOOM_OUT + 1)
 | 
				
			||||||
enum InputType
 | 
					enum InputType
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    INPUT_MOUSE_CLICK
 | 
					    INPUT_PAN,
 | 
				
			||||||
 | 
					    INPUT_MOVE,
 | 
				
			||||||
 | 
					    INPUT_SCALE,
 | 
				
			||||||
 | 
					    INPUT_CROP,
 | 
				
			||||||
 | 
					    INPUT_LEFT,
 | 
				
			||||||
 | 
					    INPUT_RIGHT,
 | 
				
			||||||
 | 
					    INPUT_UP,
 | 
				
			||||||
 | 
					    INPUT_DOWN,
 | 
				
			||||||
 | 
					    INPUT_ROTATE_LEFT,
 | 
				
			||||||
 | 
					    INPUT_ROTATE_RIGHT,
 | 
				
			||||||
 | 
					    INPUT_ZOOM_IN,
 | 
				
			||||||
 | 
					    INPUT_ZOOM_OUT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const KeyType INPUT_KEYS[INPUT_COUNT]
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    KEY_SPACE,
 | 
				
			||||||
 | 
					    KEY_T,
 | 
				
			||||||
 | 
					    KEY_S,
 | 
				
			||||||
 | 
					    KEY_C,
 | 
				
			||||||
 | 
					    KEY_LEFT,
 | 
				
			||||||
 | 
					    KEY_RIGHT,
 | 
				
			||||||
 | 
					    KEY_UP,
 | 
				
			||||||
 | 
					    KEY_DOWN,
 | 
				
			||||||
 | 
					    KEY_Q,
 | 
				
			||||||
 | 
					    KEY_W,
 | 
				
			||||||
 | 
					    KEY_1,
 | 
				
			||||||
 | 
					    KEY_2
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Keyboard
 | 
					struct Keyboard
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool current[MOUSE_COUNT];
 | 
					    bool current[KEY_COUNT];
 | 
				
			||||||
    bool previous[MOUSE_COUNT];
 | 
					    bool previous[KEY_COUNT];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Mouse
 | 
					struct Mouse
 | 
				
			||||||
@@ -39,11 +284,14 @@ struct Mouse
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct Input
 | 
					struct Input
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Keyboard keyboard;
 | 
					 | 
				
			||||||
    Mouse mouse;
 | 
					    Mouse mouse;
 | 
				
			||||||
 | 
					    Keyboard keyboard;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool mouse_press(Mouse* self, MouseType type);
 | 
					bool mouse_press(Mouse* self, MouseType type);
 | 
				
			||||||
bool mouse_held(Mouse* self, MouseType type);
 | 
					bool mouse_held(Mouse* self, MouseType type);
 | 
				
			||||||
bool mouse_release(Mouse* self, MouseType type);
 | 
					bool mouse_release(Mouse* self, MouseType type);
 | 
				
			||||||
 | 
					bool key_press(Keyboard* self, KeyType type);
 | 
				
			||||||
 | 
					bool key_held(Keyboard* self, KeyType type);
 | 
				
			||||||
 | 
					bool key_release(Keyboard* self, KeyType type);
 | 
				
			||||||
void input_tick(Input* self);
 | 
					void input_tick(Input* self);
 | 
				
			||||||
							
								
								
									
										107
									
								
								src/preview.cpp
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								src/preview.cpp
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
#include "preview.h"
 | 
					#include "preview.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void _preview_axis_set(Preview* self);
 | 
					static void _preview_axis_set(Preview* self);
 | 
				
			||||||
static void _preview_grid_set(Preview* self);
 | 
					static s32 _preview_grid_set(Preview* self);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
_preview_axis_set(Preview* self)
 | 
					_preview_axis_set(Preview* self)
 | 
				
			||||||
@@ -16,13 +16,14 @@ _preview_axis_set(Preview* self)
 | 
				
			|||||||
    glBindVertexArray(0);
 | 
					    glBindVertexArray(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					/* Sets and returns the grid's vertices */
 | 
				
			||||||
 | 
					static s32
 | 
				
			||||||
_preview_grid_set(Preview* self)
 | 
					_preview_grid_set(Preview* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    std::vector<f32> vertices;
 | 
					    std::vector<f32> vertices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s32 verticalLineCount = PREVIEW_SIZE.x / MIN(self->settings->previewGridSizeX, PREVIEW_GRID_MIN);
 | 
					    s32 verticalLineCount = (s32)(PREVIEW_SIZE.x / MIN(self->settings->previewGridSizeX, PREVIEW_GRID_MIN));
 | 
				
			||||||
    s32 horizontalLineCount = PREVIEW_SIZE.y / MIN(self->settings->previewGridSizeY, PREVIEW_GRID_MIN);
 | 
					    s32 horizontalLineCount = (s32)(PREVIEW_SIZE.y / MIN(self->settings->previewGridSizeY, PREVIEW_GRID_MIN));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Vertical */
 | 
					    /* Vertical */
 | 
				
			||||||
    for (s32 i = 0; i <= verticalLineCount; i++)
 | 
					    for (s32 i = 0; i <= verticalLineCount; i++)
 | 
				
			||||||
@@ -48,22 +49,23 @@ _preview_grid_set(Preview* self)
 | 
				
			|||||||
        vertices.push_back(normY);
 | 
					        vertices.push_back(normY);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self->gridVertexCount = (s32)vertices.size();
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    glBindVertexArray(self->gridVAO);
 | 
					    glBindVertexArray(self->gridVAO);
 | 
				
			||||||
    glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO);
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, self->gridVBO);
 | 
				
			||||||
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(f32), vertices.data(), GL_DYNAMIC_DRAW);
 | 
					    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(f32), vertices.data(), GL_DYNAMIC_DRAW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glEnableVertexAttribArray(0);
 | 
					    glEnableVertexAttribArray(0);
 | 
				
			||||||
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0);
 | 
					    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(f32), (void*)0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (s32)vertices.size();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
preview_init(Preview* self, Anm2* anm2, Resources* resources, Input* input, Settings* settings)
 | 
					preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, s32* animationID, Resources* resources, Settings* settings)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    self->anm2 = anm2;
 | 
					    self->anm2 = anm2;
 | 
				
			||||||
 | 
					    self->reference = reference;
 | 
				
			||||||
 | 
					    self->animationID = animationID;
 | 
				
			||||||
    self->resources = resources;
 | 
					    self->resources = resources;
 | 
				
			||||||
    self->input = input;
 | 
					 | 
				
			||||||
    self->settings = settings;
 | 
					    self->settings = settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Framebuffer + texture */
 | 
					    /* Framebuffer + texture */
 | 
				
			||||||
@@ -137,14 +139,11 @@ void
 | 
				
			|||||||
preview_tick(Preview* self)
 | 
					preview_tick(Preview* self)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    self->settings->previewZoom = CLAMP(self->settings->previewZoom, PREVIEW_ZOOM_MIN, PREVIEW_ZOOM_MAX);
 | 
					    self->settings->previewZoom = CLAMP(self->settings->previewZoom, PREVIEW_ZOOM_MIN, PREVIEW_ZOOM_MAX);
 | 
				
			||||||
    
 | 
					 
 | 
				
			||||||
    self->oldGridSize = glm::vec2(self->settings->previewGridSizeX, self->settings->previewGridSizeY);
 | 
					    Anm2Animation* animation = anm2_animation_from_id(self->anm2, *self->animationID);
 | 
				
			||||||
    self->oldGridOffset = glm::vec2(self->settings->previewGridOffsetX, self->settings->previewGridOffsetY);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (self->animationID > -1)
 | 
					    if (animation)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Anm2Animation* animation = &self->anm2->animations[self->animationID];     
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (self->isPlaying)
 | 
					        if (self->isPlaying)
 | 
				
			||||||
        {  
 | 
					        {  
 | 
				
			||||||
            self->time += (f32)self->anm2->fps / TICK_RATE;
 | 
					            self->time += (f32)self->anm2->fps / TICK_RATE;
 | 
				
			||||||
@@ -162,7 +161,7 @@ preview_draw(Preview* self)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    GLuint shaderLine = self->resources->shaders[SHADER_LINE];
 | 
					    GLuint shaderLine = self->resources->shaders[SHADER_LINE];
 | 
				
			||||||
    GLuint shaderTexture = self->resources->shaders[SHADER_TEXTURE];
 | 
					    GLuint shaderTexture = self->resources->shaders[SHADER_TEXTURE];
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    f32 zoomFactor = self->settings->previewZoom / 100.0f;
 | 
					    f32 zoomFactor = self->settings->previewZoom / 100.0f;
 | 
				
			||||||
    glm::vec2 ndcPan = glm::vec2(-self->settings->previewPanX / (PREVIEW_SIZE.x / 2.0f), -self->settings->previewPanY / (PREVIEW_SIZE.y / 2.0f));
 | 
					    glm::vec2 ndcPan = glm::vec2(-self->settings->previewPanX / (PREVIEW_SIZE.x / 2.0f), -self->settings->previewPanY / (PREVIEW_SIZE.y / 2.0f));
 | 
				
			||||||
    glm::mat4 previewTransform = glm::translate(glm::mat4(1.0f), glm::vec3(ndcPan, 0.0f));
 | 
					    glm::mat4 previewTransform = glm::translate(glm::mat4(1.0f), glm::vec3(ndcPan, 0.0f));
 | 
				
			||||||
@@ -183,12 +182,18 @@ preview_draw(Preview* self)
 | 
				
			|||||||
    /* Grid */
 | 
					    /* Grid */
 | 
				
			||||||
    if (self->settings->previewIsGrid)
 | 
					    if (self->settings->previewIsGrid)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if 
 | 
					        static ivec2 previousGridSize = {-1, -1};
 | 
				
			||||||
        (
 | 
					        static ivec2 previousGridOffset = {-1, -1};
 | 
				
			||||||
            (ivec2(self->settings->previewGridSizeX, self->settings->previewGridSizeY) != self->oldGridSize) ||
 | 
					        static s32 gridVertexCount = -1;
 | 
				
			||||||
            (ivec2(self->settings->previewGridOffsetX, self->settings->previewGridOffsetY) != self->oldGridOffset)
 | 
					        ivec2 gridSize = ivec2(self->settings->previewGridSizeX, self->settings->previewGridSizeY);
 | 
				
			||||||
        )
 | 
					        ivec2 gridOffset = ivec2(self->settings->previewGridOffsetX, self->settings->previewGridOffsetY);
 | 
				
			||||||
            _preview_grid_set(self);
 | 
					
 | 
				
			||||||
 | 
					        if (previousGridSize != gridSize || previousGridOffset != gridOffset)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            gridVertexCount = _preview_grid_set(self);
 | 
				
			||||||
 | 
					            previousGridSize = gridSize;
 | 
				
			||||||
 | 
					            previousGridOffset = gridOffset;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        glUseProgram(shaderLine);
 | 
					        glUseProgram(shaderLine);
 | 
				
			||||||
        glBindVertexArray(self->gridVAO);
 | 
					        glBindVertexArray(self->gridVAO);
 | 
				
			||||||
@@ -200,7 +205,7 @@ preview_draw(Preview* self)
 | 
				
			|||||||
            self->settings->previewGridColorR, self->settings->previewGridColorG, self->settings->previewGridColorB, self->settings->previewGridColorA
 | 
					            self->settings->previewGridColorR, self->settings->previewGridColorG, self->settings->previewGridColorB, self->settings->previewGridColorA
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        glDrawArrays(GL_LINES, 0, self->gridVertexCount);
 | 
					        glDrawArrays(GL_LINES, 0, gridVertexCount);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
        glBindVertexArray(0);
 | 
					        glBindVertexArray(0);
 | 
				
			||||||
        glUseProgram(0);
 | 
					        glUseProgram(0);
 | 
				
			||||||
@@ -230,33 +235,32 @@ preview_draw(Preview* self)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        glDrawArrays(GL_LINES, 2, 2);
 | 
					        glDrawArrays(GL_LINES, 2, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        glBindVertexArray(0);
 | 
					        glBindVertexArray(0);
 | 
				
			||||||
        glUseProgram(0);
 | 
					        glUseProgram(0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Anm2Animation* animation = anm2_animation_from_id(self->anm2, *self->animationID);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    /* Animation */
 | 
					    /* Animation */
 | 
				
			||||||
    if (self->animationID > -1)
 | 
					    if (animation)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Anm2Frame rootFrame = Anm2Frame{};
 | 
					        Anm2Frame rootFrame;
 | 
				
			||||||
        Anm2Animation* animation = &self->anm2->animations[self->animationID];     
 | 
					        anm2_frame_from_time(self->anm2, &rootFrame, Anm2Reference{ANM2_ROOT, 0, 0}, *self->animationID, self->time);
 | 
				
			||||||
        bool isRootFrame = anm2_frame_from_time(self->anm2, animation, &rootFrame, ANM2_ROOT_ANIMATION, 0, self->time);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Layers (Reversed) */
 | 
					        /* Layers */
 | 
				
			||||||
        for (auto & [id, layerAnimation] : animation->layerAnimations)
 | 
					        for (auto & [id, layerAnimation] : animation->layerAnimations)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
 | 
					            if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Anm2Layer* layer = &self->anm2->layers[id];
 | 
					            Anm2Frame frame;
 | 
				
			||||||
            Anm2Frame frame = layerAnimation.frames[0];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            anm2_frame_from_time(self->anm2, animation, &frame, ANM2_LAYER_ANIMATION, id, self->time);
 | 
					            anm2_frame_from_time(self->anm2, &frame, Anm2Reference{ANM2_LAYER, id, 0}, *self->animationID, self->time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!frame.isVisible)
 | 
					            if (!frame.isVisible)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Texture* texture = &self->resources->textures[layer->spritesheetID];
 | 
					            Texture* texture = &self->resources->textures[self->anm2->layers[id].spritesheetID];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (texture->isInvalid)
 | 
					            if (texture->isInvalid)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
@@ -264,7 +268,7 @@ preview_draw(Preview* self)
 | 
				
			|||||||
            glm::mat4 layerTransform = previewTransform;
 | 
					            glm::mat4 layerTransform = previewTransform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            glm::vec2 position = self->settings->previewIsRootTransform ? (frame.position + rootFrame.position) : frame.position;
 | 
					            glm::vec2 position = self->settings->previewIsRootTransform ? (frame.position + rootFrame.position) : frame.position;
 | 
				
			||||||
            glm::vec2 scale = self->settings->previewIsRootTransform ? (frame.scale / 100.0f) * (rootFrame.scale / 100.0f) : (frame.scale / 100.0f);
 | 
					            glm::vec2 scale = frame.scale / 100.0f;
 | 
				
			||||||
            glm::vec2 ndcPos = position / (PREVIEW_SIZE / 2.0f);
 | 
					            glm::vec2 ndcPos = position / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
            glm::vec2 ndcPivotOffset = (frame.pivot * scale) / (PREVIEW_SIZE / 2.0f);
 | 
					            glm::vec2 ndcPivotOffset = (frame.pivot * scale) / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
            glm::vec2 ndcScale = (frame.size * scale) / (PREVIEW_SIZE / 2.0f);
 | 
					            glm::vec2 ndcScale = (frame.size * scale) / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
@@ -276,7 +280,6 @@ preview_draw(Preview* self)
 | 
				
			|||||||
            layerTransform = glm::translate(layerTransform, glm::vec3(-ndcPivotOffset, 0.0f));
 | 
					            layerTransform = glm::translate(layerTransform, glm::vec3(-ndcPivotOffset, 0.0f));
 | 
				
			||||||
            layerTransform = glm::scale(layerTransform, glm::vec3(ndcScale, 1.0f));
 | 
					            layerTransform = glm::scale(layerTransform, glm::vec3(ndcScale, 1.0f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
            glm::vec2 uvMin = frame.crop / glm::vec2(texture->size);
 | 
					            glm::vec2 uvMin = frame.crop / glm::vec2(texture->size);
 | 
				
			||||||
            glm::vec2 uvMax = (frame.crop + frame.size) / glm::vec2(texture->size);
 | 
					            glm::vec2 uvMax = (frame.crop + frame.size) / glm::vec2(texture->size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -305,17 +308,13 @@ preview_draw(Preview* self)
 | 
				
			|||||||
            glUseProgram(0);
 | 
					            glUseProgram(0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Root */
 | 
					        if (animation->rootAnimation.isVisible && rootFrame.isVisible)
 | 
				
			||||||
        if 
 | 
					 | 
				
			||||||
        (isRootFrame && animation->rootAnimation.isVisible && rootFrame.isVisible)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            glm::mat4 rootTransform = previewTransform;
 | 
					            glm::mat4 rootTransform = previewTransform;
 | 
				
			||||||
            glm::vec2 ndcPos = (rootFrame.position - (ATLAS_SIZES[TEXTURE_TARGET] / 2.0f)) / (PREVIEW_SIZE / 2.0f);
 | 
					            glm::vec2 ndcPos = (rootFrame.position - (PREVIEW_TARGET_SIZE / 2.0f)) / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
            glm::vec2 ndcScale = ATLAS_SIZES[TEXTURE_TARGET] / (PREVIEW_SIZE / 2.0f);
 | 
					            glm::vec2 ndcScale = PREVIEW_TARGET_SIZE / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
            glm::vec2 ndcPivot = (-ATLAS_SIZES[TEXTURE_TARGET] / 2.0f) / (PREVIEW_SIZE / 2.0f);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            rootTransform = glm::translate(rootTransform, glm::vec3(ndcPos, 0.0f));
 | 
					            rootTransform = glm::translate(rootTransform, glm::vec3(ndcPos, 0.0f));
 | 
				
			||||||
            rootTransform = glm::rotate(rootTransform, glm::radians(rootFrame.rotation), glm::vec3(0, 0, 1));
 | 
					 | 
				
			||||||
            rootTransform = glm::scale(rootTransform, glm::vec3(ndcScale, 1.0f));
 | 
					            rootTransform = glm::scale(rootTransform, glm::vec3(ndcScale, 1.0f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            f32 vertices[] = ATLAS_UV_VERTICES(TEXTURE_TARGET);
 | 
					            f32 vertices[] = ATLAS_UV_VERTICES(TEXTURE_TARGET);
 | 
				
			||||||
@@ -346,17 +345,15 @@ preview_draw(Preview* self)
 | 
				
			|||||||
        /* Pivots */
 | 
					        /* Pivots */
 | 
				
			||||||
        if (self->settings->previewIsShowPivot)
 | 
					        if (self->settings->previewIsShowPivot)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
		    for (auto it = animation->layerAnimations.rbegin(); it != animation->layerAnimations.rend(); it++)
 | 
					            /* Layers (Reversed) */
 | 
				
			||||||
 | 
					            for (auto & [id, layerAnimation] : animation->layerAnimations)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                s32 id = it->first;
 | 
					 | 
				
			||||||
                Anm2LayerAnimation layerAnimation = it->second;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
 | 
					                if (!layerAnimation.isVisible || layerAnimation.frames.size() <= 0)
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                Anm2Frame frame = layerAnimation.frames[0];
 | 
					                Anm2Frame frame;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                anm2_frame_from_time(self->anm2, animation, &frame, ANM2_LAYER_ANIMATION, id, self->time);
 | 
					                anm2_frame_from_time(self->anm2, &frame, Anm2Reference{ANM2_LAYER, id, 0}, *self->animationID, self->time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!frame.isVisible)
 | 
					                if (!frame.isVisible)
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
@@ -365,8 +362,8 @@ preview_draw(Preview* self)
 | 
				
			|||||||
                    
 | 
					                    
 | 
				
			||||||
                glm::vec2 position = self->settings->previewIsRootTransform ? (frame.position + rootFrame.position) : frame.position;
 | 
					                glm::vec2 position = self->settings->previewIsRootTransform ? (frame.position + rootFrame.position) : frame.position;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                glm::vec2 ndcPos = (position - (ATLAS_SIZES[TEXTURE_PIVOT] / 2.0f)) / (PREVIEW_SIZE / 2.0f);
 | 
					                glm::vec2 ndcPos = (position - (PREVIEW_PIVOT_SIZE / 2.0f)) / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
                glm::vec2 ndcScale = ATLAS_SIZES[TEXTURE_PIVOT] / (PREVIEW_SIZE / 2.0f);
 | 
					                glm::vec2 ndcScale = PREVIEW_PIVOT_SIZE / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                pivotTransform = glm::translate(pivotTransform, glm::vec3(ndcPos, 0.0f));
 | 
					                pivotTransform = glm::translate(pivotTransform, glm::vec3(ndcPos, 0.0f));
 | 
				
			||||||
                pivotTransform = glm::scale(pivotTransform, glm::vec3(ndcScale, 1.0f));
 | 
					                pivotTransform = glm::scale(pivotTransform, glm::vec3(ndcScale, 1.0f));
 | 
				
			||||||
@@ -403,21 +400,19 @@ preview_draw(Preview* self)
 | 
				
			|||||||
            if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0)
 | 
					            if (!nullAnimation.isVisible || nullAnimation.frames.size() <= 0)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Anm2Frame frame = nullAnimation.frames[0];
 | 
					            Anm2Frame frame;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            anm2_frame_from_time(self->anm2, animation, &frame, ANM2_NULL_ANIMATION, id, self->time);
 | 
					            anm2_frame_from_time(self->anm2, &frame, Anm2Reference{ANM2_NULL, id, 0}, *self->animationID, self->time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!frame.isVisible)
 | 
					            if (!frame.isVisible)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Anm2Null* null = NULL;
 | 
					            Anm2Null* null = &self->anm2->nulls[id];
 | 
				
			||||||
 | 
					 | 
				
			||||||
            null = &self->anm2->nulls[id];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            glm::mat4 nullTransform = previewTransform;
 | 
					            glm::mat4 nullTransform = previewTransform;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            TextureType textureType = null->isShowRect ? TEXTURE_SQUARE : TEXTURE_TARGET;
 | 
					            TextureType textureType = null->isShowRect ? TEXTURE_SQUARE : TEXTURE_TARGET;
 | 
				
			||||||
            glm::vec2 size = null->isShowRect ? PREVIEW_POINT_SIZE : ATLAS_SIZES[TEXTURE_TARGET];
 | 
					            glm::vec2 size = null->isShowRect ? PREVIEW_POINT_SIZE : PREVIEW_TARGET_SIZE;
 | 
				
			||||||
            glm::vec2 pos = self->settings->previewIsRootTransform ? frame.position + (rootFrame.position) - (size / 2.0f) : frame.position - (size / 2.0f);
 | 
					            glm::vec2 pos = self->settings->previewIsRootTransform ? frame.position + (rootFrame.position) - (size / 2.0f) : frame.position - (size / 2.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            glm::vec2 ndcPos = pos / (PREVIEW_SIZE / 2.0f);
 | 
					            glm::vec2 ndcPos = pos / (PREVIEW_SIZE / 2.0f);
 | 
				
			||||||
@@ -477,8 +472,6 @@ preview_draw(Preview* self)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glUseProgram(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
 | 
					    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,9 @@ static const vec2 PREVIEW_CENTER = {0, 0};
 | 
				
			|||||||
#define PREVIEW_GRID_MAX 1000
 | 
					#define PREVIEW_GRID_MAX 1000
 | 
				
			||||||
#define PREVIEW_GRID_OFFSET_MIN 0
 | 
					#define PREVIEW_GRID_OFFSET_MIN 0
 | 
				
			||||||
#define PREVIEW_GRID_OFFSET_MAX 100
 | 
					#define PREVIEW_GRID_OFFSET_MAX 100
 | 
				
			||||||
 | 
					#define PREVIEW_MOVE_STEP 1
 | 
				
			||||||
 | 
					#define PREVIEW_ROTATE_STEP 1
 | 
				
			||||||
 | 
					#define PREVIEW_SCALE_STEP 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const f32 PREVIEW_AXIS_VERTICES[] = 
 | 
					static const f32 PREVIEW_AXIS_VERTICES[] = 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -26,16 +29,20 @@ static const f32 PREVIEW_AXIS_VERTICES[] =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static const vec2 PREVIEW_NULL_RECT_SIZE = {100, 100};
 | 
					static const vec2 PREVIEW_NULL_RECT_SIZE = {100, 100};
 | 
				
			||||||
static const vec2 PREVIEW_POINT_SIZE = {2, 2};
 | 
					static const vec2 PREVIEW_POINT_SIZE = {2, 2};
 | 
				
			||||||
 | 
					static const vec2 PREVIEW_PIVOT_SIZE = {4, 4};
 | 
				
			||||||
static const vec4 PREVIEW_ROOT_TINT = COLOR_GREEN;
 | 
					static const vec4 PREVIEW_ROOT_TINT = COLOR_GREEN;
 | 
				
			||||||
static const vec4 PREVIEW_NULL_TINT = COLOR_BLUE;
 | 
					static const vec4 PREVIEW_NULL_TINT = COLOR_BLUE;
 | 
				
			||||||
static const vec4 PREVIEW_PIVOT_TINT = COLOR_RED;
 | 
					static const vec4 PREVIEW_PIVOT_TINT = COLOR_RED;
 | 
				
			||||||
 | 
					static const vec2 PREVIEW_TARGET_SIZE = {16, 16};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Preview
 | 
					struct Preview
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Anm2* anm2 = NULL;
 | 
					    Anm2* anm2 = NULL;
 | 
				
			||||||
 | 
					    Anm2Reference* reference = NULL;
 | 
				
			||||||
    Input* input = NULL;
 | 
					    Input* input = NULL;
 | 
				
			||||||
    Resources* resources = NULL;
 | 
					    Resources* resources = NULL;
 | 
				
			||||||
    Settings* settings = NULL;
 | 
					    Settings* settings = NULL;
 | 
				
			||||||
 | 
					    s32* animationID = NULL;
 | 
				
			||||||
    GLuint axisVAO;
 | 
					    GLuint axisVAO;
 | 
				
			||||||
    GLuint axisVBO;
 | 
					    GLuint axisVBO;
 | 
				
			||||||
    GLuint fbo;
 | 
					    GLuint fbo;
 | 
				
			||||||
@@ -50,14 +57,9 @@ struct Preview
 | 
				
			|||||||
    GLuint textureVBO;
 | 
					    GLuint textureVBO;
 | 
				
			||||||
    bool isPlaying = false;
 | 
					    bool isPlaying = false;
 | 
				
			||||||
    f32 time = 0;
 | 
					    f32 time = 0;
 | 
				
			||||||
    ivec2 oldGridOffset = {-1, -1};
 | 
					 | 
				
			||||||
    ivec2 oldGridSize = {-1, -1};
 | 
					 | 
				
			||||||
    ivec2 viewport = PREVIEW_SIZE;
 | 
					 | 
				
			||||||
    s32 animationID = -1;
 | 
					 | 
				
			||||||
    s32 gridVertexCount = -1;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void preview_init(Preview* self, Anm2* anm2, Resources* resources, Input* input, Settings* settings);
 | 
					void preview_init(Preview* self, Anm2* anm2, Anm2Reference* reference, s32* animationID, Resources* resources, Settings* settings);
 | 
				
			||||||
void preview_draw(Preview* self);
 | 
					void preview_draw(Preview* self);
 | 
				
			||||||
void preview_tick(Preview* self);
 | 
					void preview_tick(Preview* self);
 | 
				
			||||||
void preview_free(Preview* self);
 | 
					void preview_free(Preview* self);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,6 +52,7 @@ enum SettingsItem
 | 
				
			|||||||
    SETTINGS_PREVIEW_BACKGROUND_COLOR_B,
 | 
					    SETTINGS_PREVIEW_BACKGROUND_COLOR_B,
 | 
				
			||||||
    SETTINGS_PREVIEW_BACKGROUND_COLOR_A,
 | 
					    SETTINGS_PREVIEW_BACKGROUND_COLOR_A,
 | 
				
			||||||
    SETTINGS_EDITOR_IS_GRID,
 | 
					    SETTINGS_EDITOR_IS_GRID,
 | 
				
			||||||
 | 
					    SETTINGS_EDITOR_IS_GRID_SNAP,
 | 
				
			||||||
    SETTINGS_EDITOR_IS_BORDER,
 | 
					    SETTINGS_EDITOR_IS_BORDER,
 | 
				
			||||||
    SETTINGS_EDITOR_PAN_X,
 | 
					    SETTINGS_EDITOR_PAN_X,
 | 
				
			||||||
    SETTINGS_EDITOR_PAN_Y,
 | 
					    SETTINGS_EDITOR_PAN_Y,
 | 
				
			||||||
@@ -98,6 +99,7 @@ struct Settings
 | 
				
			|||||||
    f32 previewBackgroundColorB = 0.286f;
 | 
					    f32 previewBackgroundColorB = 0.286f;
 | 
				
			||||||
    f32 previewBackgroundColorA = 1.0f;
 | 
					    f32 previewBackgroundColorA = 1.0f;
 | 
				
			||||||
    bool editorIsGrid = true;
 | 
					    bool editorIsGrid = true;
 | 
				
			||||||
 | 
					    bool editorIsGridSnap = true;
 | 
				
			||||||
    bool editorIsBorder = true;
 | 
					    bool editorIsBorder = true;
 | 
				
			||||||
    f32 editorPanX = 0.0f;
 | 
					    f32 editorPanX = 0.0f;
 | 
				
			||||||
    f32 editorPanY = 0.0f;
 | 
					    f32 editorPanY = 0.0f;
 | 
				
			||||||
@@ -144,6 +146,7 @@ static const SettingsEntry SETTINGS_ENTRIES[SETTINGS_COUNT] =
 | 
				
			|||||||
    {"previewBackgroundColorB=", "previewBackgroundColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorB)},
 | 
					    {"previewBackgroundColorB=", "previewBackgroundColorB=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorB)},
 | 
				
			||||||
    {"previewBackgroundColorA=", "previewBackgroundColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorA)},
 | 
					    {"previewBackgroundColorA=", "previewBackgroundColorA=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, previewBackgroundColorA)},
 | 
				
			||||||
    {"editorIsGrid=", "editorIsGrid=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGrid)},
 | 
					    {"editorIsGrid=", "editorIsGrid=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGrid)},
 | 
				
			||||||
 | 
					    {"editorIsGridSnap=", "editorIsGridSnap=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsGridSnap)},
 | 
				
			||||||
    {"editorIsBorder=", "editorIsBorder=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsBorder)},
 | 
					    {"editorIsBorder=", "editorIsBorder=%i", SETTINGS_TYPE_BOOL, offsetof(Settings, editorIsBorder)},
 | 
				
			||||||
    {"editorPanX=", "editorPanX=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanX)},
 | 
					    {"editorPanX=", "editorPanX=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanX)},
 | 
				
			||||||
    {"editorPanY=", "editorPanY=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanY)},
 | 
					    {"editorPanY=", "editorPanY=%f", SETTINGS_TYPE_FLOAT, offsetof(Settings, editorPanY)},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,7 @@ _tick(State* state)
 | 
				
			|||||||
	input_tick(&state->input);
 | 
						input_tick(&state->input);
 | 
				
			||||||
	editor_tick(&state->editor);
 | 
						editor_tick(&state->editor);
 | 
				
			||||||
	preview_tick(&state->preview);
 | 
						preview_tick(&state->preview);
 | 
				
			||||||
 | 
						tool_tick(&state->tool);
 | 
				
			||||||
	dialog_tick(&state->dialog);
 | 
						dialog_tick(&state->dialog);
 | 
				
			||||||
	imgui_tick(&state->imgui);
 | 
						imgui_tick(&state->imgui);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -104,10 +105,29 @@ init(State* state)
 | 
				
			|||||||
	printf(STRING_INFO_GLEW_INIT);
 | 
						printf(STRING_INFO_GLEW_INIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resources_init(&state->resources);
 | 
						resources_init(&state->resources);
 | 
				
			||||||
	dialog_init(&state->dialog, &state->anm2, &state->resources, state->window);
 | 
						dialog_init(&state->dialog, &state->anm2, &state->reference, &state->resources, state->window);
 | 
				
			||||||
	
 | 
						tool_init(&state->tool, &state->input);
 | 
				
			||||||
	preview_init(&state->preview, &state->anm2, &state->resources, &state->input, &state->settings);
 | 
					
 | 
				
			||||||
	editor_init(&state->editor, &state->resources, &state->settings);
 | 
						preview_init
 | 
				
			||||||
 | 
						(
 | 
				
			||||||
 | 
							&state->preview, 
 | 
				
			||||||
 | 
							&state->anm2, 
 | 
				
			||||||
 | 
							&state->reference, 
 | 
				
			||||||
 | 
							&state->animationID,
 | 
				
			||||||
 | 
							&state->resources, 
 | 
				
			||||||
 | 
							&state->settings
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						editor_init
 | 
				
			||||||
 | 
						(
 | 
				
			||||||
 | 
							&state->editor, 
 | 
				
			||||||
 | 
							&state->anm2, 
 | 
				
			||||||
 | 
							&state->reference, 
 | 
				
			||||||
 | 
							&state->animationID, 
 | 
				
			||||||
 | 
							&state->spritesheetID, 
 | 
				
			||||||
 | 
							&state->resources, 
 | 
				
			||||||
 | 
							&state->settings
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	imgui_init
 | 
						imgui_init
 | 
				
			||||||
	(
 | 
						(
 | 
				
			||||||
@@ -116,10 +136,14 @@ init(State* state)
 | 
				
			|||||||
		&state->resources,
 | 
							&state->resources,
 | 
				
			||||||
		&state->input,
 | 
							&state->input,
 | 
				
			||||||
		&state->anm2,
 | 
							&state->anm2,
 | 
				
			||||||
 | 
							&state->reference,
 | 
				
			||||||
 | 
							&state->animationID,
 | 
				
			||||||
 | 
							&state->spritesheetID,
 | 
				
			||||||
		&state->editor,
 | 
							&state->editor,
 | 
				
			||||||
		&state->preview,
 | 
							&state->preview,
 | 
				
			||||||
		&state->settings,
 | 
							&state->settings,
 | 
				
			||||||
		state->window, 
 | 
							&state->tool,
 | 
				
			||||||
 | 
							state->window,
 | 
				
			||||||
		&state->glContext
 | 
							&state->glContext
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -144,10 +168,11 @@ loop(State* state)
 | 
				
			|||||||
        	SDL_Delay(TICK_DELAY - (state->tick - state->lastTick));
 | 
					        	SDL_Delay(TICK_DELAY - (state->tick - state->lastTick));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_tick(state);
 | 
							_tick(state);
 | 
				
			||||||
		_draw(state);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		state->lastTick = state->tick;
 | 
							state->lastTick = state->tick;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_draw(state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/state.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/state.h
									
									
									
									
									
								
							@@ -18,14 +18,18 @@ struct State
 | 
				
			|||||||
	Editor editor;
 | 
						Editor editor;
 | 
				
			||||||
	Preview preview;
 | 
						Preview preview;
 | 
				
			||||||
    Anm2 anm2;
 | 
					    Anm2 anm2;
 | 
				
			||||||
 | 
						Anm2Reference reference;
 | 
				
			||||||
	Resources resources;
 | 
						Resources resources;
 | 
				
			||||||
	Settings settings;
 | 
						Settings settings;
 | 
				
			||||||
 | 
						Tool tool;
 | 
				
			||||||
 | 
						bool isArgument = false;
 | 
				
			||||||
 | 
						bool isRunning = true;
 | 
				
			||||||
	char argument[PATH_MAX] = STRING_EMPTY;
 | 
						char argument[PATH_MAX] = STRING_EMPTY;
 | 
				
			||||||
	char startPath[PATH_MAX] = STRING_EMPTY;
 | 
						char startPath[PATH_MAX] = STRING_EMPTY;
 | 
				
			||||||
	bool isArgument = false;
 | 
						s32 animationID = -1;
 | 
				
			||||||
	u64 tick = 0;
 | 
						s32 spritesheetID = -1;
 | 
				
			||||||
	u64 lastTick = 0;
 | 
						u64 lastTick = 0;
 | 
				
			||||||
	bool isRunning = true;
 | 
						u64 tick = 0;
 | 
				
			||||||
}; 
 | 
					}; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void init(State* state);
 | 
					void init(State* state);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								src/tool.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/tool.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					#include "tool.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					tool_init(Tool* self, Input* input)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    self->input = input;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					tool_tick(Tool* self)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (!self->isEnabled) return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
						/* Input handling */
 | 
				
			||||||
 | 
						if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_PAN]))
 | 
				
			||||||
 | 
							self->type = TOOL_PAN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_MOVE]))
 | 
				
			||||||
 | 
							self->type = TOOL_MOVE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_SCALE]))
 | 
				
			||||||
 | 
							self->type = TOOL_SCALE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (key_press(&self->input->keyboard, INPUT_KEYS[INPUT_CROP]))
 | 
				
			||||||
 | 
							self->type = TOOL_CROP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if 
 | 
				
			||||||
 | 
						(
 | 
				
			||||||
 | 
							key_press(&self->input->keyboard, INPUT_KEYS[INPUT_ROTATE_LEFT]) ||
 | 
				
			||||||
 | 
							key_press(&self->input->keyboard, INPUT_KEYS[INPUT_ROTATE_RIGHT])
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
							self->type = TOOL_ROTATE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								src/tool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/tool.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "input.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TOOL_COUNT (TOOL_CROP + 1)
 | 
				
			||||||
 | 
					enum ToolType
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TOOL_PAN,
 | 
				
			||||||
 | 
					    TOOL_MOVE,
 | 
				
			||||||
 | 
					    TOOL_ROTATE,
 | 
				
			||||||
 | 
					    TOOL_SCALE,
 | 
				
			||||||
 | 
					    TOOL_CROP
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Tool
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Input* input = NULL;
 | 
				
			||||||
 | 
					    ToolType type = TOOL_PAN;
 | 
				
			||||||
 | 
					    bool isEnabled = false;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void tool_init(Tool* self, Input* input);
 | 
				
			||||||
 | 
					void tool_tick(Tool* self);
 | 
				
			||||||
		Reference in New Issue
	
	Block a user