/* libsswf_tag_doaction.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */

/*

Copyright (c) 2002-2008 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

/** \file
 *
 * \brief The implementation of the sswf::TagDoAction class
 *
 * This file declares the body of the functions which are not
 * inline. It is part of the SSWF library.
 */

#include	"sswf/libsswf.h"

using namespace sswf;

/////////////////////////////////////////// TagDoAction

/** \class sswf::TagDoAction
 *
 * \brief This tag hold an ActionScript.
 *
 * This tag represents an ActionScript in binary form.
 *
 * An ActionScript is executed each time the given frame is
 * played back unless a Sprite identifier is specified, in
 * that case the ActionScript is an initialization script an
 * thus it will be run only once.
 *
 * \sa SWF_TAG_DO_ACTION
 * \sa SWF_TAG_DO_INIT_ACTION
 * \sa <a href="../SWFalexref.html#tag_doaction">SWF Alexis' Reference&mdash;DoAction</a>
 * \sa <a href="../SWFalexref.html#tag_doinitaction">SWF Alexis' Reference&mdash;DoInitAction</a>
 * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
 */



/** \fn Vectors& sswf::TagDoAction::Actions(void)
 *
 * \brief Retrieve a reference to the actions array.
 *
 * This function can be used to retrieve a reference to the array
 * used to save all the actions.
 *
 * You can then add the actions you create to this array. You
 * most certainly will want to save a sswf::Action::Duplicate(void) const
 * and use the
 * sswf::MemoryManager::MemAttach(MemBuffer *ptr, size_t size, const char *info)
 * function to attach these duplicates to your sswf::TagDoAction object.
 *
 * The main idea in letting you have direct access to the array is
 * for you to be able to manage the list they way you want: you can
 * then insert new actions anywhere, append them, delete them...
 *
 * \return A Vectors reference of all the actions in this TagDoAction
 * object.
 *
 * \sa SetAction(const Action& action)
 */


/** \brief Initialize a TagDoAction
 *
 * The constructor assumes that there is no actions and no
 * sprite reference to this tag.
 *
 * \param parent The parent of this TagDoAction
 */
TagDoAction::TagDoAction(TagBase *parent)
	: TagBase("doaction", parent)
{
	assert(parent != 0, "a Place tag must have a parent");

	f_sprite = 0;
	//f_actions = ... -- auto-init in action!
}



/** \brief Returns the type flags of a TagDoAction.
 *
 * This function returns CONTROL since an ActionScript is viewed as a
 * control tag and not a definition.
 *
 * It returns SCRIPT since obviously it includes a script.
 *
 * It returns ONE because you are supposed to have only one per frame.
 * This is not really enforced by the players.
 *
 * It returns REFERENCE thought if you do not define a sprite reference
 * this is obviously not the case.
 *
 * \return A set of swf_type_t flags
 */
TagBase::swf_type_t TagDoAction::TypeFlags(void) const
{
	return SWF_TYPE_CONTROL | SWF_TYPE_SCRIPT | SWF_TYPE_ONE | SWF_TYPE_REFERENCE;
}


/** \brief Append one action.
 *
 * First create some action, then append the action using this function.
 *
 * The new action is added at the very end. The input action is duplicated
 * internally and thus the input can be modified by the caller afterward.
 *
 * For more control over the list of actions, use the Actions() function
 * to retrieve the vector and manage the vector yourself.
 *
 * \warning
 * If you manage the vector of actions yourself, you should be careful
 * and use the MemAttach() function of your TagDoAction() to make sure
 * that the memory allocated by each action is released at the time
 * the TagDoAction() is destroyed. Once added to the actions vector of
 * a TagDoAction(), the actions become the property of the TagDoAction()
 * object.
 *
 * \param action The action to duplicate and append at the end of the list
 *
 * \sa sswf::TagDoAction::Actions(void)
 */
void TagDoAction::SetAction(const Action& action)
{
	Action		*a;

	a = action.Duplicate();
	MemAttach(a, sizeof(Action), "action duplicate in DoAction tag");

	f_actions.Set(-1, a);
}


/** \brief Set the sprite reference identifier.
 *
 * This function saves the specified identifier as a sprite identifier
 * or set to zero to remove the reference.
 *
 * When a sswf::TagDoAction has a reference to a sprite, it because
 * the ActionScript to execute once to initialize the Sprite it
 * references (Similar to a constructor in C++).
 *
 * By default, a TagDoAction has no sprite reference.
 *
 * \param sprite The identifier of the sprite to reference
 */
void TagDoAction::SetSprite(sswf_id_t sprite)
{
	f_sprite = sprite;
}


/** \brief Determine the minimum version required to save this tag.
 *
 * This function checks whether a sprite referenced was defined; if so,
 * then the minimum version is set to 6.
 *
 * Then it goes through the whole list of actions recursively to
 * determine what the required minimum version is to save these
 * actions.
 *
 * \return An error code if something goes wrong
 *
 * \sa sswf::Action::MinimumListVersion(const Vectors& list)
 */
ErrorManager::error_code_t TagDoAction::PreSave(void)
{
	if(f_sprite != 0) {
		MinimumVersion(6);
	}

	MinimumVersion(Action::MinimumListVersion(f_actions));

	return ErrorManager::ERROR_CODE_NONE;
}


/** \brief Save the TagDoAction in the specified Data buffer
 *
 * This function saves the TagDoAction in the specified Data buffer.
 *
 * This means saving the list of actions and, when specified, the
 * reference to the given sprite.
 *
 * The list of actions is saved using the
 * sswf::Action::SaveList(TagBase *parent, const Vectors *list, Data& data, const Vectors *extra)
 * function.
 *
 * \return An error code if something goes wrong
 *
 * \sa sswf::Action::SaveList(TagBase *parent, const Vectors *list, Data& data, const Vectors *extra)
 */
ErrorManager::error_code_t TagDoAction::Save(Data& data)
{
	Data				sub_data;
	Action				*action;
	ErrorManager::error_code_t	ec;

	if(f_actions.Count() > 0) {
		action = dynamic_cast<Action *>(f_actions.Get(0));
		ec = action->SaveList(&f_actions, sub_data);
		if(ec != ErrorManager::ERROR_CODE_NONE) {
			return ec;
		}
	}

	if(f_sprite != 0) {
		SaveTag(data, SWF_TAG_DO_INIT_ACTION, sub_data.ByteSize() + 2);
		data.PutShort(f_sprite);
	}
	else {
		SaveTag(data, SWF_TAG_DO_ACTION, sub_data.ByteSize());
	}
	data.Append(sub_data);

	return ErrorManager::ERROR_CODE_NONE;
}




/* The following options fold the documentation; use 'zi' to turn on and off
 *
 * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
 */
