📄 button.c
字号:
/* Ming, an SWF output library Copyright (C) 2002 Opaque Industries - http://www.opaque.net/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* $Id: button.c,v 1.29 2008/06/01 13:09:43 krechert Exp $ */#include <stdlib.h>#include "button.h"#include "character.h"#include "error.h"#include "matrix.h"#include "outputblock.h"#include "method.h"#include "soundinstance.h"#include "browserfont.h"#include "action.h"#include "filter.h"#include "../position.h"#include "libming.h"#define RECORD_HASFILTER (1<<4)#define RECORD_HASBLEND (1<<5)struct SWFButtonRecord_s{ byte flags; unsigned short layer; SWFCharacter character; SWFPosition position; SWFCXform cxform; int blendMode; SWFFilterList filterList;};struct actionRecord{ int flags; SWFAction action;};/* typedef struct actionRecord* ActionRecord; */struct SWFButton_s{ struct SWFCharacter_s character; int menuflag; int nRecords; SWFButtonRecord *records; int nActions; struct actionRecord *actions; SWFButtonSound sounds; SWFScalingGrid grid; SWFOutput out;};struct SWFButtonSound_s{ struct SWFBlock_s character; SWFButton button; SWFSoundInstance sounds[4];};static SWFButtonRecord newSWFButtonRecord(byte flags, SWFCharacter character, unsigned short layer, SWFMatrix matrix){ SWFButtonRecord record = (SWFButtonRecord) malloc(sizeof(struct SWFButtonRecord_s)); record->flags = flags; record->character = character; record->layer = layer; record->position = newSWFPosition(matrix); record->filterList = NULL; record->blendMode = 0; return record;}#define BUTTONRECORD_INCREMENT 8static void SWFButton_addRecord(SWFButton button, SWFButtonRecord record){ if ( button->nRecords % BUTTONRECORD_INCREMENT == 0 ) { button->records = (SWFButtonRecord*) realloc(button->records, (button->nRecords + BUTTONRECORD_INCREMENT) * sizeof(SWFButtonRecord)); } button->records[button->nRecords++] = record; SWFCharacter_addDependency((SWFCharacter)button, (SWFCharacter)record->character);}/* note: replaces action, doesn't append.. */void SWFButton_addAction(SWFButton button, SWFAction action, int flags){ if ( SWFCharacter_isFinished((SWFCharacter)button) ) SWF_error("Can't alter a button after it's been added to another character"); if ( button->nActions % BUTTONRECORD_INCREMENT == 0 ) { button->actions = (struct actionRecord*) realloc(button->actions, (button->nActions + BUTTONRECORD_INCREMENT) * sizeof(struct actionRecord)); } button->actions[button->nActions].action = action; button->actions[button->nActions].flags = flags; ++button->nActions;}/* adds a shape character * Add a shape character to a button for given states * possible states: * SWFBUTTON_HIT * SWFBUTTON_DOWN * SWFBUTTON_OVER * SWFBUTTON_UP * states can be combined using the binary or operator * deprecated! use SWFButton_addCharacter instead */void SWFButton_addShape(SWFButton button, SWFCharacter character, byte flags){ SWFMatrix m; SWF_warnOnce("SWFButton_addShape is deprecated\nUse SWFButton_addCharacter instead\n"); if ( SWFCharacter_isFinished((SWFCharacter)button) ) SWF_error("Can't alter a button after it's been added to another character"); m = newSWFMatrix(0, 0, 0, 0, 0, 0); SWFCharacter_getDependencies((SWFCharacter)character, &CHARACTER(button)->dependencies, &CHARACTER(button)->nDependencies); SWFCharacter_addDependency((SWFCharacter)button, (SWFCharacter)character); SWFCharacter_setFinished(character); SWFButton_addRecord(button, newSWFButtonRecord(flags, character, 0, m));}/* adds a character * Add a character to a button for given states * possible states: * SWFBUTTON_HIT * SWFBUTTON_DOWN * SWFBUTTON_OVER * SWFBUTTON_UP * states can be combined using the binary or operator * returns a SWFButtonRecord object which can be further modified. */SWFButtonRecordSWFButton_addCharacter(SWFButton button /* button object */, SWFCharacter character /* character to be added */, byte state /* state description */){ SWFMatrix m; SWFButtonRecord record; SWFCharacter **depsPtr = &CHARACTER(button)->dependencies; int *depCount = &CHARACTER(button)->nDependencies; if ( SWFCharacter_isFinished((SWFCharacter)button) ) { SWF_warn("Can't alter a button after it's been added to another character"); return NULL; } SWFCharacter_getDependencies(character, depsPtr, depCount); SWFCharacter_addDependency((SWFCharacter)button, character); SWFCharacter_setFinished(character); m = newSWFMatrix(0, 0, 0, 0, 0, 0); record = newSWFButtonRecord(state, character, 0, m); SWFButton_addRecord(button, record); return record;}voidSWFButtonRecord_setDepth(SWFButtonRecord b, int depth){ b->layer = depth;}/* * sets blend mode * Sets an alternative blend mode instead of default alpha blend. * possible modes are: * SWFBLEND_MODE_NORMAL * SWFBLEND_MODE_LAYER * SWFBLEND_MODE_MULT * SWFBLEND_MODE_SCREEN * SWFBLEND_MODE_DARKEN * SWFBLEND_MODE_ADD * SWFBLEND_MODE_SUB * SWFBLEND_MODE_DIFF * SWFBLEND_MODE_DIFF * SWFBLEND_MODE_INV * SWFBLDEN_MODE_ALPHA * SWFBLEND_MDOE_ERASE * SWFBLEND_MDOE_OVERLAY * SWFBLEND_MODE_HARDLIGHT */voidSWFButtonRecord_setBlendMode(SWFButtonRecord record, int mode){ record->blendMode = mode; record->flags |= RECORD_HASBLEND;}/* * adds a surface filter * Adds a bitmap filter to the display object. * See SWFFilter for possible filter objects. */void SWFButtonRecord_addFilter(SWFButtonRecord record, SWFFilter filter){ if(record->filterList == NULL) { record->filterList = newSWFFilterList(); record->flags |= RECORD_HASFILTER; } SWFFilterList_add(record->filterList, filter);}void SWFButtonRecord_move(SWFButtonRecord record, double x, double y){ SWFPosition_move(record->position, x, y);}void SWFButtonRecord_moveTo(SWFButtonRecord record, double x, double y){ SWFPosition_moveTo(record->position, x, y);}void SWFButtonRecord_rotate(SWFButtonRecord record, double deg){ SWFPosition_rotate(record->position, deg);}void SWFButtonRecord_rotateTo(SWFButtonRecord record, double deg){ SWFPosition_rotateTo(record->position, deg);}void SWFButtonRecord_scale(SWFButtonRecord record, double scaleX, double scaleY){ SWFPosition_scaleXY(record->position, scaleX, scaleY);}void SWFButtonRecord_scaleTo(SWFButtonRecord record, double scaleX, double scaleY){ SWFPosition_scaleXYTo(record->position, scaleX, scaleY);}void SWFButtonRecord_skewX(SWFButtonRecord record, double skewX){ SWFPosition_skewX(record->position, skewX);}void SWFButtonRecord_skewXTo(SWFButtonRecord record, double skewX){ SWFPosition_skewXTo(record->position, skewX);}void SWFButtonRecord_skewY(SWFButtonRecord record, double skewY){ SWFPosition_skewY(record->position, skewY);}void SWFButtonRecord_skewYTo(SWFButtonRecord record, double skewY){ SWFPosition_skewYTo(record->position, skewY);}void SWFButton_setMenu(SWFButton button, int flag){ button->menuflag = flag;}void writeSWFButtonToMethod(SWFBlock block, SWFByteOutputMethod method, void *data){ SWFButton button = (SWFButton)block; SWFOutput_writeToMethod(button->out, method, data);}int completeSWFButton(SWFBlock block){ SWFButton button = (SWFButton)block; SWFButtonRecord record; SWFOutput out = newSWFOutput(); int i, length = 0, layer; byte *offset; SWFOutput_writeUInt16(out, CHARACTERID(button)); SWFOutput_writeUInt8(out, button->menuflag); /* fill in offset later */ offset = SWFOutput_getCurPos(out); SWFOutput_writeUInt16(out, 0); for(i=0; i<button->nRecords; ++i) { record = button->records[i]; SWFOutput_writeUInt8(out, record->flags); SWFOutput_writeUInt16(out, CHARACTERID(record->character)); layer = record->layer; if(layer == 0 && block->swfVersion >= 5) layer = i+1; SWFOutput_writeUInt16(out, layer); SWFOutput_writeMatrix(out, SWFPosition_getMatrix(record->position)); SWFOutput_writeUInt8(out, 0); /* blank CXForm */ if(record->flags & RECORD_HASFILTER) SWFOutput_writeFilterList(out, record->filterList); if(record->flags & RECORD_HASBLEND) SWFOutput_writeUInt8(out, record->blendMode); } SWFOutput_writeUInt8(out, 0); /* end buttons */ length = SWFOutput_getLength(out) - 3; if(button->nActions > 0) { *offset = length&0xff; *(offset+1) = (length>>8)&0xff; } for(i=0; i<button->nActions; ++i) { SWFAction_compile(button->actions[i].action, block->swfVersion, &length); if(i == button->nActions-1) SWFOutput_writeUInt16(out, 0); else SWFOutput_writeUInt16(out, length + 4); SWFOutput_writeUInt16(out, button->actions[i].flags); SWFOutput_writeAction(out, button->actions[i].action); } button->out = out; return SWFOutput_getLength(out);}void destroySWFButton(SWFButton button){ int i; for ( i=0; i<button->nRecords; ++i ) { if ( button->records[i]->position != NULL ) destroySWFPosition(button->records[i]->position); if( button->records[i]->filterList != NULL) destroySWFFilterList(button->records[i]->filterList); free(button->records[i]); } if ( button->records != NULL ) free(button->records); for ( i=0; i<button->nActions; ++i ) destroySWFAction(button->actions[i].action); if ( button->actions != NULL ) free(button->actions); destroySWFOutput(button->out); destroySWFCharacter((SWFCharacter) button);}static int onSWFButtonPlace(SWFDisplayItem item, SWFBlockList list){ SWFButton button = (SWFButton)SWFDisplayItem_getCharacter(item); if(!button->grid) return 0; SWFBlockList_addBlock(list, (SWFBlock)button->grid); return 1;}static int onSWFButtonFrame(SWFDisplayItem item, SWFBlockList list){ SWFButton button = (SWFButton)SWFDisplayItem_getCharacter(item); if(!button->sounds) return 0; SWFBlockList_addBlock(list, (SWFBlock)button->sounds); return 1;}SWFButtonnewSWFButton(){ SWFButton button = (SWFButton) malloc(sizeof(struct SWFButton_s)); SWFCharacterInit((SWFCharacter)button); CHARACTERID(button) = ++SWF_gNumCharacters; BLOCK(button)->type = SWF_DEFINEBUTTON2; BLOCK(button)->writeBlock = writeSWFButtonToMethod; BLOCK(button)->complete = completeSWFButton; BLOCK(button)->dtor = (destroySWFBlockMethod) destroySWFButton; ((SWFCharacter)button)->onPlace = onSWFButtonPlace; ((SWFCharacter)button)->onFrame = onSWFButtonFrame; button->menuflag = 0; button->nRecords = 0; button->records = NULL; button->nActions = 0; button->actions = NULL; button->out = NULL; button->sounds = NULL; button->grid = NULL; return button;}SWFSoundInstanceSWFButton_addSound(SWFButton button, SWFSound sound, byte flag){ if ( SWFCharacter_isFinished((SWFCharacter)button) ) SWF_error("Can't alter a button after it's been added to another character"); if ( button->sounds == NULL ) { button->sounds = newSWFButtonSound(button);// SWFCharacter_addDependency((SWFCharacter)button->sounds,// (SWFCharacter)button); } SWFCharacter_addDependency((SWFCharacter)button, (SWFCharacter)sound); return SWFButtonSound_setSound(button->sounds, sound, flag);}voiddestroySWFButtonSound(SWFButtonSound buttonSound){ free(buttonSound);}/* NOTE: at least F5 and F6 do not write an extra 0 style byte if there is no sound for a particular transition the docs say otherwise */voidwriteSWFButtonSoundToMethod(SWFBlock block, SWFByteOutputMethod method, void *data){ SWFButtonSound buttonSound = (SWFButtonSound)block; int i; methodWriteUInt16(CHARACTERID(buttonSound->button), method, data); for ( i=0; i<4; ++i ) { SWFSoundInstance sound = buttonSound->sounds[i]; if(sound) writeSWFSoundInstanceToMethod((SWFBlock)sound, method, data); else methodWriteUInt16(0, method, data); }}intcompleteSWFButtonSound(SWFBlock block){ int size = 2; /* button ID */ int i; SWFButtonSound buttonSound = (SWFButtonSound)block; for ( i=0; i<4; ++i ) { SWFSoundInstance sound = buttonSound->sounds[i]; if(sound) size += completeSWFSoundInstance((SWFBlock)sound); else size += 2; } return size;}SWFButtonSoundnewSWFButtonSound(SWFButton button){ SWFButtonSound buttonSound = (SWFButtonSound) malloc(sizeof(struct SWFButtonSound_s)); SWFBlock block = (SWFBlock)buttonSound; SWFBlockInit(block); block->type = SWF_DEFINEBUTTONSOUND; block->writeBlock = writeSWFButtonSoundToMethod; block->complete = completeSWFButtonSound; block->dtor = (destroySWFBlockMethod) destroySWFButtonSound; buttonSound->button = button; buttonSound->sounds[0] = NULL; buttonSound->sounds[1] = NULL; buttonSound->sounds[2] = NULL; buttonSound->sounds[3] = NULL; return buttonSound;}SWFSoundInstanceSWFButtonSound_setSound(SWFButtonSound sounds, SWFSound sound, byte flags){ if ( flags == SWFBUTTON_OVERUPTOIDLE ) return (sounds->sounds[0] = newSWFSoundInstance(sound)); else if ( flags == SWFBUTTON_IDLETOOVERUP ) return (sounds->sounds[1] = newSWFSoundInstance(sound)); else if ( flags == SWFBUTTON_OVERUPTOOVERDOWN ) return (sounds->sounds[2] = newSWFSoundInstance(sound)); else if ( flags == SWFBUTTON_OVERDOWNTOOVERUP ) return (sounds->sounds[3] = newSWFSoundInstance(sound)); else SWF_error("SWFButtonSound_setSound: Invalid flags argument"); return NULL;}/* * set a 9 slice scaling grid to this sprite / movieclip / button * This function sets a 9 slice scaling grid to buttons / sprites / movieclips * * 1 2 3 * 4 5 6 * 7 8 9 * * x, y, w and h define a rectangle, which is the dimension of the center slice (5) * all other slices are determined out of the characters bounds and the defined rect. * While slice 5 is scalde vertical and horizontal, slice 2 and 8 are only scale horizontal. * slice 4 and 6 only vertical. the 4 corner slices are not scaled (1, 3, 7, 9). */void SWFButton_setScalingGrid(SWFButton b, int x, int y, int w, int h){ if(b->grid) destroySWFScalingGrid(b->grid); b->grid = newSWFScalingGrid((SWFCharacter)b, x, y, w, h);}/* * removes the scaling grid */void SWFButton_removeScalingGrid(SWFButton b){ if(b->grid) { destroySWFScalingGrid(b->grid); b->grid = NULL; }}/* * Local variables: * tab-width: 2 * c-basic-offset: 2 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -