Moving all player controls to script

stable-5.2
Sven Eberhardt 2009-05-25 05:01:26 -04:00
parent 6e35727259
commit ff15ca7441
7 changed files with 413 additions and 10 deletions

View File

@ -83,7 +83,7 @@
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\deps\lib"
IgnoreDefaultLibraryNames="LIBCMT"
IgnoreDefaultLibraryNames="LIBCMT,LIBCMTD"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\intermediate\vc9\Engine\Debug\clonk.pdb"
SubSystem="2"
@ -183,7 +183,7 @@
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\deps\lib"
IgnoreDefaultLibraryNames="LIBCMT"
IgnoreDefaultLibraryNames="LIBCMT,LIBCMTD"
ProgramDatabaseFile="..\intermediate\vc9\clonk.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
@ -283,7 +283,7 @@
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\deps\lib"
IgnoreDefaultLibraryNames="LIBCMT"
IgnoreDefaultLibraryNames="LIBCMT,LIBCMTD"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\intermediate\vc9\engine\ExtremeDebug\clonk.pdb"
SubSystem="2"
@ -383,7 +383,7 @@
LinkIncremental="1"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\deps\lib"
IgnoreDefaultLibraryNames="LIBCMT"
IgnoreDefaultLibraryNames="LIBCMT,LIBCMTD"
ProgramDatabaseFile="..\intermediate\vc9\clonk.pdb"
SubSystem="1"
RandomizedBaseAddress="1"
@ -481,7 +481,7 @@
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="..\deps\lib"
IgnoreDefaultLibraryNames="LIBCMT"
IgnoreDefaultLibraryNames="LIBCMT,LIBCMTD"
GenerateDebugInformation="true"
ProgramDatabaseFile="..\intermediate\vc9\Engine\DebugConsole\clonk.pdb"
SubSystem="1"
@ -6884,6 +6884,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\C4PlayerControl.cpp"
>
</File>
<File
RelativePath="src\C4PlayerInfo.cpp"
>
@ -10202,6 +10206,10 @@
RelativePath="inc\C4Player.h"
>
</File>
<File
RelativePath=".\inc\C4PlayerControl.h"
>
</File>
<File
RelativePath="inc\C4PlayerInfo.h"
>

View File

@ -162,7 +162,7 @@ struct C4KeyCodeEx
return Key == v2.Key && dwShift == v2.dwShift;
}
void CompileFunc(StdCompiler *pComp);
void CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBufIfUndefined=NULL);
C4KeyCodeEx(C4KeyCode Key = KEY_Default, C4KeyShiftState Shift = KEYS_None, bool fIsRepeated = false)
: Key(Key), dwShift(Shift), fRepeated(fIsRepeated) {}

View File

@ -0,0 +1,204 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
// Input to player control mapping
#ifndef INC_C4PlayerControl
#define INC_C4PlayerControl
#ifndef BIG_C4INCLUDE
#include <C4KeyboardInput.h>
#endif
// one control definition, e.g. "Left", "Throw", etc.
class C4PlayerControlDef
{
private:
StdCopyStrBuf sIdentifier; // name as seen in script and config
StdCopyStrBuf sGUIName; // name as displayed to player
StdCopyStrBuf sGUIDesc; // key description displayed to player in config dialog
bool fIsHoldKey; // if true, the control can be in down and up state
int32_t iRepeat; // if >0, the key will generate successive events when held down
bool fDefaultDisabled; // if true, the control is disabled by default and needs to be enabled by script
public:
C4PlayerControlDef() : fIsHoldKey(false), fDefaultDisabled(false) {}
~C4PlayerControlDef() {};
void CompileFunc(StdCompiler *pComp);
const char *GetIdentifier() const { return sIdentifier.getData(); }
const char *GetGUIName() const { return sGUIName.getData(); }
const char *GetGUIDesc() const { return sGUIDesc.getData(); }
//C4PlayerControlDef &operator =(const C4PlayerControlDef &src);
bool operator ==(const C4PlayerControlDef &cmp) const;
};
// CON_* constants are indices into the C4PlayerControlDefs list
enum { CON_None = -1 }; // No/undefined control
// list of all known player control definitions
class C4PlayerControlDefs
{
private:
typedef std::vector<C4PlayerControlDef> DefVecImpl;
DefVecImpl Defs;
public:
void CompileFunc(StdCompiler *pComp);
void MergeFrom(const C4PlayerControlDefs &Src); // copy all defs from source file; overwrite defs of same name if found
C4PlayerControlDef *GetControlByIndex(int32_t idx);
int32_t GetControlIndexByIdentifier(const char *szIdentifier) const; // return CON_None for not found
};
// a key/mouse/gamepad assignment to a PlayerControlDef
class C4PlayerControlAssignment
{
private:
// KeyCombo list:
// if size()>1, the control is triggered only if this combo is fulfilled
// used for simultanuous keypresses or sequences
struct KeyComboItem
{
C4KeyCodeEx Key;
StdCopyStrBuf sKeyName;
void CompileFunc(StdCompiler *pComp);
bool operator ==(const KeyComboItem &cmp) const { return sKeyName==cmp.sKeyName; }
};
typedef std::vector<KeyComboItem> KeyComboVec;
KeyComboVec KeyCombo;
bool fComboIsSequence; // if true, the keys must be pressed in sequence. Otherwise, they must be pressed simultanuously
// trigger key: key/mouse/gamepad event triggering this assignment. For combinations, the last key of the combo.
C4KeyCodeEx TriggerKey;
StdCopyStrBuf sControlName; // name of the control to be executed on this key
int32_t iControl; // the control to be executed on this key, i.e. the resolved sControlName
bool fAlwaysUnhandled; // if true, the key will not block handling of other keys even if it got handled
// action to be performed on the control upon this key
enum TriggerModes
{
CTM_Default=0, // standard behaviour: The control will be triggered
CTM_Hold, // the control will be put into "down"-mode
CTM_Release, // the hold mode of the control will be released
} eTriggerMode;
public:
C4PlayerControlAssignment() : TriggerKey(), iControl(CON_None), fAlwaysUnhandled(false), eTriggerMode(CTM_Default) {}
~C4PlayerControlAssignment();
void CompileFunc(StdCompiler *pComp);
void ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
bool operator ==(const C4PlayerControlAssignment &cmp) const; // doesn't compare resolved TriggerKey/iControl
const char *GetControlName() const { return sControlName.getData(); }
};
// a set of key/mouse/gamepad assignments to all controls
class C4PlayerControlAssignmentSet
{
private:
StdCopyStrBuf sName;
typedef std::vector<C4PlayerControlAssignment> AssignmentsVec;
AssignmentsVec Assignments;
public:
C4PlayerControlAssignmentSet() {}
~C4PlayerControlAssignmentSet() {}
void CompileFunc(StdCompiler *pComp);
void ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
void MergeFrom(const C4PlayerControlAssignmentSet &Src, bool fLowPrio); // take over all assignments defined in Src
const char *GetName() const { return sName.getData(); }
C4PlayerControlAssignment *GetAssignmentByControlName(const char *szControlName) const;
};
// list of C4PlayerControlAssignmentSet
class C4PlayerControlAssignmentSets
{
private:
typedef std::list<C4PlayerControlAssignmentSet> AssignmentSetList;
public:
C4PlayerControlAssignmentSets() {}
~C4PlayerControlAssignmentSets() {}
void CompileFunc(StdCompiler *pComp);
void MergeFrom(const C4PlayerControlAssignmentSets &Src, bool fLowPrio); // take over all assignments in known sets and new sets defined in Src
};
// contents of one PlayerControls.txt file
class C4PlayerControlFile
{
private:
C4PlayerControlDef ControlDefs;
C4PlayerControlAssignmentSets AssignmentSets;
public:
bool Load(C4Group &hGroup, const char *szFilename);
const C4PlayerControlDef &GetControlDefs() const { return ControlDefs; }
const C4PlayerControlAssignmentSets &GetAssignmentSets() const { return AssignmentSets; }
};
// runtime information about a player's control
class C4PlayerControl
{
private:
struct RecentKey
{
C4KeyCodeEx Key;
int32_t iFrame;
};
// shortcut
C4PlayerControlDefs &ControlDefs;
// async values
C4PlayerControlAssignmentSet *pControlSet; // the control set used by this player
std::list<C4KeyBinding *> KeyBindings; // keys registered into Game.KeyboardInput
std::list<RecentKey> RecentKeys; // keys pressed recently; for combinations
std::vector<C4KeyCodeEx> DownKeys; // keys currently held down
// sync values
struct
{
std::vector<int32_t> ControlDownStates; // indexed by C4PlayerControlID: Down-state of a control. 0=up, 100=down; values inbetween e.g. for gamepad sticks
std::vector<int32_t> ControlDisableStates; // indexed by C4PlayerControlID: Disable-states of controls. >0 is disabled.
void CompileFunc(StdCompiler *pComp);
} Sync;
// callbacks from Game.KeyboardInput
bool ProcessKeyPress(C4KeyCodeEx key, int32_t iKeyIndex);
bool ProcessKeyDown(C4KeyCodeEx key, int32_t iKeyIndex);
bool ProcessKeyUp(C4KeyCodeEx key, int32_t iKeyIndex);
public:
C4PlayerControl();
~C4PlayerControl() { Clear(); }
void Clear();
void RegisterKeyset(C4PlayerControlAssignmentSet *pKeyset); // register all keys into Game.KeyboardInput creating KeyBindings
};
#endif // INC_C4PlayerControl

View File

@ -441,7 +441,7 @@ StdStrBuf C4KeyCodeEx::ToString(bool fHumanReadable, bool fShort)
/* ----------------- C4KeyCodeEx ------------------ */
void C4KeyCodeEx::CompileFunc(StdCompiler *pComp)
void C4KeyCodeEx::CompileFunc(StdCompiler *pComp, StdStrBuf *pOutBufIfUndefined)
{
if (pComp->isCompiler())
{
@ -464,7 +464,18 @@ void C4KeyCodeEx::CompileFunc(StdCompiler *pComp)
// last section: convert to key code
C4KeyCode eCode = String2KeyCode(sCode);
if (eCode == KEY_Undefined)
pComp->excCorrupt("undefined key code: %s", sCode.getData());
{
if (pOutBufIfUndefined)
{
// unknown key, but an output buffer for unknown keys was provided. Use it.
pOutBufIfUndefined->Take(sCode);
eCode = KEY_Default;
}
else
{
pComp->excCorrupt("undefined key code: %s", sCode.getData());
}
}
dwShift = dwSetShift;
Key = eCode;
}

View File

@ -0,0 +1,179 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
// Input to player control mapping
#include <C4Include.h>
#include <C4PlayerControl.h>
/* C4PlayerControlDef */
void C4PlayerControlDef::CompileFunc(StdCompiler *pComp)
{
if (!pComp->Name("ControlDef")) pComp->excNotFound("ControlDef");
pComp->Value(mkNamingAdapt(mkParAdapt(sIdentifier, StdCompiler::RCT_Idtf), "Identifier", "None"));
pComp->Value(mkNamingAdapt(mkParAdapt(sGUIName, StdCompiler::RCT_All), "GUIName", "undefined"));
pComp->Value(mkNamingAdapt(mkParAdapt(sGUIDesc, StdCompiler::RCT_All), "GUIDesc", ""));
pComp->Value(mkNamingAdapt(fIsHoldKey, "IsHoldKey", false));
pComp->Value(mkNamingAdapt(iRepeat, "Repeat", 0));
pComp->Value(mkNamingAdapt(fDefaultDisabled, "DefaultDisabled", false));
pComp->NameEnd();
}
bool C4PlayerControlDef::operator ==(const C4PlayerControlDef &cmp) const
{
return sIdentifier == cmp.sIdentifier
&& sGUIName == cmp.sGUIName
&& sGUIDesc == cmp.sGUIDesc
&& fIsHoldKey == cmp.fIsHoldKey
&& iRepeat == cmp.iRepeat
&& fDefaultDisabled == cmp.fDefaultDisabled;
}
/* C4PlayerControlDefs */
void C4PlayerControlDefs::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Defs, StdCompiler::SEP_NONE), "ControlDefs", DefVecImpl()));
}
void C4PlayerControlDefs::MergeFrom(const C4PlayerControlDefs &Src)
{
// copy all defs from source file; overwrite defs of same name if found
for (DefVecImpl::const_iterator i = Src.Defs.begin(); i != Src.Defs.end(); ++i)
{
const C4PlayerControlDef &SrcDef = *i;
// overwrite if def of same name existed
int32_t iPrevIdx = GetControlIndexByIdentifier(SrcDef.GetIdentifier());
if (iPrevIdx != CON_None)
{
Defs[iPrevIdx] = SrcDef;
}
else
{
// new def: Append a copy
Defs.push_back(SrcDef);
}
}
}
C4PlayerControlDef *C4PlayerControlDefs::GetControlByIndex(int32_t idx)
{
// safe index
if (idx<0 || idx>=Defs.size()) return NULL;
return &(Defs[idx]);
}
int32_t C4PlayerControlDefs::GetControlIndexByIdentifier(const char *szIdentifier) const
{
for (DefVecImpl::const_iterator i = Defs.begin(); i != Defs.end(); ++i)
if (SEqual((*i).GetIdentifier(), szIdentifier))
return i-Defs.begin();
return CON_None;
}
/* C4PlayerControlAssignment */
void C4PlayerControlAssignment::KeyComboItem::CompileFunc(StdCompiler *pComp)
{
// if key is compiled, also store as a string into KeyName for later resolving
if (pComp->isCompiler())
{
sKeyName.Clear();
pComp->Value(mkParAdapt(Key, &sKeyName));
if (!sKeyName)
{
// key was not assigned during compilation - this means it's a regular key (or undefined)
// store this as the name
sKeyName.Copy(Key.ToString(false, false));
}
}
else
{
// decompiler: Just write the stored key name; regardless of whether it's a key, undefined or a reference
pComp->Value(mkParAdapt(sKeyName, StdCompiler::RCT_Idtf));
}
}
void C4PlayerControlAssignment::CompileFunc(StdCompiler *pComp)
{
if (!pComp->Name("ControlAssignment")) pComp->excNotFound("ControlAssignment");
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(KeyCombo), "Key", KeyComboVec()));
pComp->Value(mkNamingAdapt(mkParAdapt(sControlName, StdCompiler::RCT_Idtf), "Control", "None"));
pComp->Value(mkNamingAdapt(fAlwaysUnhandled, "AlwaysUnhandled", false));
const StdEnumEntry<TriggerModes> TriggerModeNames[] = {
{ "Default", CTM_Default },
{ "Hold", CTM_Hold },
{ "Release", CTM_Release },
{ NULL, CTM_Default } };
pComp->Value(mkNamingAdapt(mkEnumAdapt<TriggerModes, int32_t>(eTriggerMode, TriggerModeNames), "TriggerMode", CTM_Default));
pComp->NameEnd();
}
bool C4PlayerControlAssignment::operator ==(const C4PlayerControlAssignment &cmp) const
{
// doesn't compare resolved TriggerKey/iControl
return KeyCombo == cmp.KeyCombo
&& sControlName == cmp.sControlName
&& fAlwaysUnhandled == cmp.fAlwaysUnhandled
&& eTriggerMode == cmp.eTriggerMode;
}
/* C4PlayerControlAssignmentSet */
void C4PlayerControlAssignmentSet::CompileFunc(StdCompiler *pComp)
{
if (!pComp->Name("ControlAssignmentSet")) pComp->excNotFound("ControlAssignmentSet");
pComp->Value(mkNamingAdapt(mkParAdapt(sName, StdCompiler::RCT_Idtf), "Name", "None"));
pComp->Value(mkNamingAdapt(mkSTLContainerAdapt(Assignments, StdCompiler::SEP_NONE), "Key", AssignmentsVec()));
pComp->NameEnd();
}
void C4PlayerControlAssignmentSet::MergeFrom(const C4PlayerControlAssignmentSet &Src, bool fLowPrio)
{
// take over all assignments defined in Src
for (AssignmentsVec::const_iterator i = Src.Assignments.begin(); i != Src.Assignments.end(); ++i)
{
const C4PlayerControlAssignment &SrcAssignment = *i;
// overwrite if def of same name existed if it's not low priority anyway
C4PlayerControlAssignment *pPrevAssignment = GetAssignmentByControlName(SrcAssignment.GetControlName());
if (pPrevAssignment)
{
if (!fLowPrio) *pPrevAssignment = SrcAssignment;
}
else
{
// new def: Append a copy
Assignments.push_back(SrcAssignment);
}
}
}
C4PlayerControlAssignment *C4PlayerControlAssignmentSet::GetAssignmentByControlName(const char *szControlName) const
{
for (AssignmentsVec::const_iterator i = Assignments.begin(); i != Assignments.end(); ++i)
if (SEqual((*i).GetControlName(), szControlName))
return &*i;
return NULL;
}
/* C4PlayerControlAssignmentSets */

View File

@ -518,7 +518,7 @@ struct StdSTLContainerAdapt
// Write all entries
for (typename C::const_iterator i = rStruct.begin(); i != rStruct.end(); ++i)
{
if (i != rStruct.begin()) pComp->Seperator(eSep);
if (i != rStruct.begin() && eSep) pComp->Seperator(eSep);
pComp->Value(const_cast<T &>(*i));
}
}
@ -549,7 +549,7 @@ struct StdSTLContainerAdapt
break;
}
}
while(pComp->Seperator(eSep));
while(!eSep || pComp->Seperator(eSep));
}
}
// Operators for default checking/setting

View File

@ -107,6 +107,7 @@ public:
// ending the naming, too.
enum Sep
{
SEP_NONE=0, // No seperator ("")
SEP_SEP, // Array seperation (",")
SEP_SEP2, // Array seperation 2 (";")
SEP_SET, // Map pair seperation ("=")