Merge pull request #11614 from t895/kotlin-cheats

Android: Convert Cheats Activity to Kotlin
This commit is contained in:
Mai
2023-03-02 15:04:19 -05:00
committed by GitHub
48 changed files with 1511 additions and 1917 deletions
@@ -1,60 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
public class ARCheat extends AbstractCheat
{
@Keep
private final long mPointer;
public ARCheat()
{
mPointer = createNew();
}
@Keep
private ARCheat(long pointer)
{
mPointer = pointer;
}
@Override
public native void finalize();
private native long createNew();
public boolean supportsCreator()
{
return false;
}
public boolean supportsNotes()
{
return false;
}
@NonNull
public native String getName();
@NonNull
public native String getCode();
public native boolean getUserDefined();
public native boolean getEnabled();
@Override
protected native int trySetImpl(@NonNull String name, @NonNull String creator,
@NonNull String notes, @NonNull String code);
@Override
protected native void setEnabledImpl(boolean enabled);
@NonNull
public static native ARCheat[] loadCodes(String gameId, int revision);
public static native void saveCodes(String gameId, int revision, ARCheat[] codes);
}
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
import androidx.annotation.Keep
class ARCheat : AbstractCheat {
@Keep
private val pointer: Long
constructor() {
pointer = createNew()
}
@Keep
private constructor(pointer: Long) {
this.pointer = pointer
}
external fun finalize()
private external fun createNew(): Long
override fun supportsCreator(): Boolean = false
override fun supportsNotes(): Boolean = false
external override fun getName(): String
external override fun getCode(): String
external override fun getUserDefined(): Boolean
external override fun getEnabled(): Boolean
external override fun setEnabledImpl(enabled: Boolean)
external override fun setCheatImpl(
name: String,
creator: String,
notes: String,
code: String
): Int
companion object {
@JvmStatic
external fun loadCodes(gameId: String, revision: Int): Array<ARCheat>
@JvmStatic
external fun saveCodes(gameId: String, revision: Int, codes: Array<ARCheat>)
}
}
@@ -1,45 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.NonNull;
public abstract class AbstractCheat extends ReadOnlyCheat
{
public boolean supportsCode()
{
return true;
}
public int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes,
@NonNull String code)
{
if (!code.isEmpty() && code.charAt(0) == '$')
{
int firstLineEnd = code.indexOf('\n');
if (firstLineEnd == -1)
{
name = code.substring(1);
code = "";
}
else
{
name = code.substring(1, firstLineEnd);
code = code.substring(firstLineEnd + 1);
}
}
if (name.isEmpty())
return TRY_SET_FAIL_NO_NAME;
int result = trySetImpl(name, creator, notes, code);
if (result == TRY_SET_SUCCESS)
onChanged();
return result;
}
protected abstract int trySetImpl(@NonNull String name, @NonNull String creator,
@NonNull String notes, @NonNull String code);
}
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
import org.dolphinemu.dolphinemu.features.cheats.model.Cheat.Companion.TRY_SET_FAIL_NO_NAME
import org.dolphinemu.dolphinemu.features.cheats.model.Cheat.Companion.TRY_SET_SUCCESS
abstract class AbstractCheat : ReadOnlyCheat() {
override fun supportsCode(): Boolean {
return true
}
override fun setCheat(
name: String,
creator: String,
notes: String,
code: String
): Int {
var finalName = name
var finalCode = code
if (finalCode.isNotEmpty() && finalCode[0] == '$') {
val firstLineEnd = finalCode.indexOf('\n')
if (firstLineEnd == -1) {
finalName = finalCode.substring(1)
finalCode = ""
} else {
finalName = finalCode.substring(1, firstLineEnd)
finalCode = finalCode.substring(firstLineEnd + 1)
}
}
if (finalName.isEmpty()) return TRY_SET_FAIL_NO_NAME
val result = setCheatImpl(finalName, creator, notes, finalCode)
if (result == TRY_SET_SUCCESS) onChanged()
return result
}
protected abstract fun setCheatImpl(
name: String,
creator: String,
notes: String,
code: String
): Int
}
@@ -1,53 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public interface Cheat
{
int TRY_SET_FAIL_CODE_MIXED_ENCRYPTION = -3;
int TRY_SET_FAIL_NO_CODE_LINES = -2;
int TRY_SET_FAIL_NO_NAME = -1;
int TRY_SET_SUCCESS = 0;
// Result codes greater than 0 represent an error on the corresponding code line (one-indexed)
boolean supportsCreator();
boolean supportsNotes();
boolean supportsCode();
@NonNull
String getName();
@NonNull
default String getCreator()
{
return "";
}
@NonNull
default String getNotes()
{
return "";
}
@NonNull
default String getCode()
{
return "";
}
int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes,
@NonNull String code);
boolean getUserDefined();
boolean getEnabled();
void setEnabled(boolean enabled);
void setChangedCallback(@Nullable Runnable callback);
}
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
interface Cheat {
fun supportsCreator(): Boolean
fun supportsNotes(): Boolean
fun supportsCode(): Boolean
fun getName(): String = ""
fun getCreator(): String = ""
fun getNotes(): String = ""
fun getCode(): String = ""
fun setCheat(
name: String,
creator: String,
notes: String,
code: String
): Int
fun getUserDefined(): Boolean
fun getEnabled(): Boolean
fun setEnabled(isChecked: Boolean)
fun setChangedCallback(callback: Runnable?)
companion object {
// Result codes greater than 0 represent an error on the corresponding code line (one-indexed)
const val TRY_SET_FAIL_CODE_MIXED_ENCRYPTION = -3
const val TRY_SET_FAIL_NO_CODE_LINES = -2
const val TRY_SET_FAIL_NO_NAME = -1
const val TRY_SET_SUCCESS = 0
}
}
@@ -1,321 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import java.util.ArrayList;
import java.util.Collections;
public class CheatsViewModel extends ViewModel
{
private boolean mLoaded = false;
private int mSelectedCheatPosition = -1;
private final MutableLiveData<Cheat> mSelectedCheat = new MutableLiveData<>(null);
private final MutableLiveData<Boolean> mIsAdding = new MutableLiveData<>(false);
private final MutableLiveData<Boolean> mIsEditing = new MutableLiveData<>(false);
private final MutableLiveData<Integer> mCheatAddedEvent = new MutableLiveData<>(null);
private final MutableLiveData<Integer> mCheatChangedEvent = new MutableLiveData<>(null);
private final MutableLiveData<Integer> mCheatDeletedEvent = new MutableLiveData<>(null);
private final MutableLiveData<Integer> mGeckoCheatsDownloadedEvent = new MutableLiveData<>(null);
private final MutableLiveData<Boolean> mOpenDetailsViewEvent = new MutableLiveData<>(false);
private GraphicsModGroup mGraphicsModGroup;
private ArrayList<GraphicsMod> mGraphicsMods;
private ArrayList<PatchCheat> mPatchCheats;
private ArrayList<ARCheat> mARCheats;
private ArrayList<GeckoCheat> mGeckoCheats;
private boolean mGraphicsModsNeedSaving = false;
private boolean mPatchCheatsNeedSaving = false;
private boolean mARCheatsNeedSaving = false;
private boolean mGeckoCheatsNeedSaving = false;
public void load(String gameID, int revision)
{
if (mLoaded)
return;
mGraphicsModGroup = GraphicsModGroup.load(gameID);
mGraphicsMods = new ArrayList<>();
Collections.addAll(mGraphicsMods, mGraphicsModGroup.getMods());
mPatchCheats = new ArrayList<>();
Collections.addAll(mPatchCheats, PatchCheat.loadCodes(gameID, revision));
mARCheats = new ArrayList<>();
Collections.addAll(mARCheats, ARCheat.loadCodes(gameID, revision));
mGeckoCheats = new ArrayList<>();
Collections.addAll(mGeckoCheats, GeckoCheat.loadCodes(gameID, revision));
for (GraphicsMod mod : mGraphicsMods)
{
mod.setChangedCallback(() -> mGraphicsModsNeedSaving = true);
}
for (PatchCheat cheat : mPatchCheats)
{
cheat.setChangedCallback(() -> mPatchCheatsNeedSaving = true);
}
for (ARCheat cheat : mARCheats)
{
cheat.setChangedCallback(() -> mARCheatsNeedSaving = true);
}
for (GeckoCheat cheat : mGeckoCheats)
{
cheat.setChangedCallback(() -> mGeckoCheatsNeedSaving = true);
}
mLoaded = true;
}
public void saveIfNeeded(String gameID, int revision)
{
if (mGraphicsModsNeedSaving)
{
mGraphicsModGroup.save();
mGraphicsModsNeedSaving = false;
}
if (mPatchCheatsNeedSaving)
{
PatchCheat.saveCodes(gameID, revision, mPatchCheats.toArray(new PatchCheat[0]));
mPatchCheatsNeedSaving = false;
}
if (mARCheatsNeedSaving)
{
ARCheat.saveCodes(gameID, revision, mARCheats.toArray(new ARCheat[0]));
mARCheatsNeedSaving = false;
}
if (mGeckoCheatsNeedSaving)
{
GeckoCheat.saveCodes(gameID, revision, mGeckoCheats.toArray(new GeckoCheat[0]));
mGeckoCheatsNeedSaving = false;
}
}
public LiveData<Cheat> getSelectedCheat()
{
return mSelectedCheat;
}
public void setSelectedCheat(Cheat cheat, int position)
{
if (mIsEditing.getValue())
setIsEditing(false);
mSelectedCheat.setValue(cheat);
mSelectedCheatPosition = position;
}
public LiveData<Boolean> getIsAdding()
{
return mIsAdding;
}
public void startAddingCheat(Cheat cheat, int position)
{
mSelectedCheat.setValue(cheat);
mSelectedCheatPosition = position;
mIsAdding.setValue(true);
mIsEditing.setValue(true);
}
public void finishAddingCheat()
{
if (!mIsAdding.getValue())
throw new IllegalStateException();
mIsAdding.setValue(false);
mIsEditing.setValue(false);
Cheat cheat = mSelectedCheat.getValue();
if (cheat instanceof PatchCheat)
{
mPatchCheats.add((PatchCheat) mSelectedCheat.getValue());
cheat.setChangedCallback(() -> mPatchCheatsNeedSaving = true);
mPatchCheatsNeedSaving = true;
}
else if (cheat instanceof ARCheat)
{
mARCheats.add((ARCheat) mSelectedCheat.getValue());
cheat.setChangedCallback(() -> mPatchCheatsNeedSaving = true);
mARCheatsNeedSaving = true;
}
else if (cheat instanceof GeckoCheat)
{
mGeckoCheats.add((GeckoCheat) mSelectedCheat.getValue());
cheat.setChangedCallback(() -> mGeckoCheatsNeedSaving = true);
mGeckoCheatsNeedSaving = true;
}
else
{
throw new UnsupportedOperationException();
}
notifyCheatAdded();
}
public LiveData<Boolean> getIsEditing()
{
return mIsEditing;
}
public void setIsEditing(boolean isEditing)
{
mIsEditing.setValue(isEditing);
if (mIsAdding.getValue() && !isEditing)
{
mIsAdding.setValue(false);
setSelectedCheat(null, -1);
}
}
/**
* When a cheat is added, the integer stored in the returned LiveData
* changes to the position of that cheat, then changes back to null.
*/
public LiveData<Integer> getCheatAddedEvent()
{
return mCheatAddedEvent;
}
private void notifyCheatAdded()
{
mCheatAddedEvent.setValue(mSelectedCheatPosition);
mCheatAddedEvent.setValue(null);
}
/**
* When a cheat is edited, the integer stored in the returned LiveData
* changes to the position of that cheat, then changes back to null.
*/
public LiveData<Integer> getCheatChangedEvent()
{
return mCheatChangedEvent;
}
/**
* Notifies that an edit has been made to the contents of the currently selected cheat.
*/
public void notifySelectedCheatChanged()
{
notifyCheatChanged(mSelectedCheatPosition);
}
/**
* Notifies that an edit has been made to the contents of the cheat at the given position.
*/
public void notifyCheatChanged(int position)
{
mCheatChangedEvent.setValue(position);
mCheatChangedEvent.setValue(null);
}
/**
* When a cheat is deleted, the integer stored in the returned LiveData
* changes to the position of that cheat, then changes back to null.
*/
public LiveData<Integer> getCheatDeletedEvent()
{
return mCheatDeletedEvent;
}
public void deleteSelectedCheat()
{
Cheat cheat = mSelectedCheat.getValue();
int position = mSelectedCheatPosition;
setSelectedCheat(null, -1);
if (mPatchCheats.remove(cheat))
mPatchCheatsNeedSaving = true;
if (mARCheats.remove(cheat))
mARCheatsNeedSaving = true;
if (mGeckoCheats.remove(cheat))
mGeckoCheatsNeedSaving = true;
notifyCheatDeleted(position);
}
/**
* Notifies that the cheat at the given position has been deleted.
*/
private void notifyCheatDeleted(int position)
{
mCheatDeletedEvent.setValue(position);
mCheatDeletedEvent.setValue(null);
}
/**
* When Gecko cheats are downloaded, the integer stored in the returned LiveData
* changes to the number of cheats added, then changes back to null.
*/
public LiveData<Integer> getGeckoCheatsDownloadedEvent()
{
return mGeckoCheatsDownloadedEvent;
}
public int addDownloadedGeckoCodes(GeckoCheat[] cheats)
{
int cheatsAdded = 0;
for (GeckoCheat cheat : cheats)
{
if (!mGeckoCheats.contains(cheat))
{
mGeckoCheats.add(cheat);
cheatsAdded++;
}
}
if (cheatsAdded != 0)
{
mGeckoCheatsNeedSaving = true;
mGeckoCheatsDownloadedEvent.setValue(cheatsAdded);
mGeckoCheatsDownloadedEvent.setValue(null);
}
return cheatsAdded;
}
public LiveData<Boolean> getOpenDetailsViewEvent()
{
return mOpenDetailsViewEvent;
}
public void openDetailsView()
{
mOpenDetailsViewEvent.setValue(true);
mOpenDetailsViewEvent.setValue(false);
}
public ArrayList<GraphicsMod> getGraphicsMods()
{
return mGraphicsMods;
}
public ArrayList<PatchCheat> getPatchCheats()
{
return mPatchCheats;
}
public ArrayList<ARCheat> getARCheats()
{
return mARCheats;
}
public ArrayList<GeckoCheat> getGeckoCheats()
{
return mGeckoCheats;
}
}
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.dolphinemu.dolphinemu.features.cheats.model.ARCheat.Companion.loadCodes
import org.dolphinemu.dolphinemu.features.cheats.model.ARCheat.Companion.saveCodes
import kotlin.collections.ArrayList
class CheatsViewModel : ViewModel() {
private var loaded = false
private var selectedCheatPosition = -1
private val _selectedCheat = MutableLiveData<Cheat?>(null)
val selectedCheat: LiveData<Cheat?> get() = _selectedCheat
private val _isAdding = MutableLiveData(false)
val isAdding: LiveData<Boolean> get() = _isAdding
private val _isEditing = MutableLiveData(false)
val isEditing: LiveData<Boolean> get() = _isEditing
private val _cheatAddedEvent = MutableLiveData<Int?>(null)
val cheatAddedEvent: LiveData<Int?> get() = _cheatAddedEvent
private val _cheatChangedEvent = MutableLiveData<Int?>(null)
val cheatChangedEvent: LiveData<Int?> get() = _cheatChangedEvent
private val _cheatDeletedEvent = MutableLiveData<Int?>(null)
val cheatDeletedEvent: LiveData<Int?> get() = _cheatDeletedEvent
private val _geckoCheatsDownloadedEvent = MutableLiveData<Int?>(null)
val geckoCheatsDownloadedEvent: LiveData<Int?> get() = _geckoCheatsDownloadedEvent
private val _openDetailsViewEvent = MutableLiveData(false)
val openDetailsViewEvent: LiveData<Boolean> get() = _openDetailsViewEvent
private var graphicsModGroup: GraphicsModGroup? = null
var graphicsMods: ArrayList<GraphicsMod> = ArrayList()
var patchCheats: ArrayList<PatchCheat> = ArrayList()
var aRCheats: ArrayList<ARCheat> = ArrayList()
var geckoCheats: ArrayList<GeckoCheat> = ArrayList()
private var graphicsModsNeedSaving = false
private var patchCheatsNeedSaving = false
private var aRCheatsNeedSaving = false
private var geckoCheatsNeedSaving = false
fun load(gameID: String, revision: Int) {
if (loaded) return
graphicsModGroup = GraphicsModGroup.load(gameID)
graphicsMods.addAll(graphicsModGroup!!.mods)
patchCheats.addAll(PatchCheat.loadCodes(gameID, revision))
aRCheats.addAll(loadCodes(gameID, revision))
geckoCheats.addAll(GeckoCheat.loadCodes(gameID, revision))
for (mod in graphicsMods) {
mod.setChangedCallback { graphicsModsNeedSaving = true }
}
for (cheat in patchCheats) {
cheat.setChangedCallback { patchCheatsNeedSaving = true }
}
for (cheat in aRCheats) {
cheat.setChangedCallback { aRCheatsNeedSaving = true }
}
for (cheat in geckoCheats) {
cheat.setChangedCallback { geckoCheatsNeedSaving = true }
}
loaded = true
}
fun saveIfNeeded(gameID: String, revision: Int) {
if (graphicsModsNeedSaving) {
graphicsModGroup!!.save()
graphicsModsNeedSaving = false
}
if (patchCheatsNeedSaving) {
PatchCheat.saveCodes(gameID, revision, patchCheats.toTypedArray())
patchCheatsNeedSaving = false
}
if (aRCheatsNeedSaving) {
saveCodes(gameID, revision, aRCheats.toTypedArray())
aRCheatsNeedSaving = false
}
if (geckoCheatsNeedSaving) {
GeckoCheat.saveCodes(gameID, revision, geckoCheats.toTypedArray())
geckoCheatsNeedSaving = false
}
}
fun setSelectedCheat(cheat: Cheat?, position: Int) {
if (isEditing.value!!) setIsEditing(false)
_selectedCheat.value = cheat
selectedCheatPosition = position
}
fun startAddingCheat(cheat: Cheat?, position: Int) {
_selectedCheat.value = cheat
selectedCheatPosition = position
_isAdding.value = true
_isEditing.value = true
}
fun finishAddingCheat() {
check(isAdding.value!!)
_isAdding.value = false
_isEditing.value = false
when (val cheat = selectedCheat.value) {
is PatchCheat -> {
patchCheats.add(cheat)
cheat.setChangedCallback(Runnable { patchCheatsNeedSaving = true })
patchCheatsNeedSaving = true
}
is ARCheat -> {
aRCheats.add(cheat)
cheat.setChangedCallback(Runnable { patchCheatsNeedSaving = true })
aRCheatsNeedSaving = true
}
is GeckoCheat -> {
geckoCheats.add(cheat)
cheat.setChangedCallback(Runnable { geckoCheatsNeedSaving = true })
geckoCheatsNeedSaving = true
}
else -> throw UnsupportedOperationException()
}
notifyCheatAdded()
}
fun setIsEditing(isEditing: Boolean) {
_isEditing.value = isEditing
if (isAdding.value!! && !isEditing) {
_isAdding.value = false
setSelectedCheat(null, -1)
}
}
private fun notifyCheatAdded() {
_cheatAddedEvent.value = selectedCheatPosition
_cheatAddedEvent.value = null
}
/**
* Notifies that an edit has been made to the contents of the currently selected cheat.
*/
fun notifySelectedCheatChanged() {
notifyCheatChanged(selectedCheatPosition)
}
/**
* Notifies that an edit has been made to the contents of the cheat at the given position.
*/
private fun notifyCheatChanged(position: Int) {
_cheatChangedEvent.value = position
_cheatChangedEvent.value = null
}
fun deleteSelectedCheat() {
val cheat = selectedCheat.value
val position = selectedCheatPosition
setSelectedCheat(null, -1)
if (patchCheats.remove(cheat)) patchCheatsNeedSaving = true
if (aRCheats.remove(cheat)) aRCheatsNeedSaving = true
if (geckoCheats.remove(cheat)) geckoCheatsNeedSaving = true
notifyCheatDeleted(position)
}
/**
* Notifies that the cheat at the given position has been deleted.
*/
private fun notifyCheatDeleted(position: Int) {
_cheatDeletedEvent.value = position
_cheatDeletedEvent.value = null
}
fun addDownloadedGeckoCodes(cheats: Array<GeckoCheat>): Int {
var cheatsAdded = 0
for (cheat in cheats) {
if (!geckoCheats.contains(cheat)) {
geckoCheats.add(cheat)
cheatsAdded++
}
}
if (cheatsAdded != 0) {
geckoCheatsNeedSaving = true
_geckoCheatsDownloadedEvent.value = cheatsAdded
_geckoCheatsDownloadedEvent.value = null
}
return cheatsAdded
}
fun openDetailsView() {
_openDetailsViewEvent.value = true
_openDetailsViewEvent.value = false
}
}
@@ -1,78 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class GeckoCheat extends AbstractCheat
{
@Keep
private final long mPointer;
public GeckoCheat()
{
mPointer = createNew();
}
@Keep
private GeckoCheat(long pointer)
{
mPointer = pointer;
}
@Override
public native void finalize();
private native long createNew();
@Override
public boolean equals(@Nullable Object obj)
{
return obj != null && getClass() == obj.getClass() && equalsImpl((GeckoCheat) obj);
}
public boolean supportsCreator()
{
return true;
}
public boolean supportsNotes()
{
return true;
}
@NonNull
public native String getName();
@NonNull
public native String getCreator();
@NonNull
public native String getNotes();
@NonNull
public native String getCode();
public native boolean getUserDefined();
public native boolean getEnabled();
public native boolean equalsImpl(@NonNull GeckoCheat other);
@Override
protected native int trySetImpl(@NonNull String name, @NonNull String creator,
@NonNull String notes, @NonNull String code);
@Override
protected native void setEnabledImpl(boolean enabled);
@NonNull
public static native GeckoCheat[] loadCodes(String gameId, int revision);
public static native void saveCodes(String gameId, int revision, GeckoCheat[] codes);
@Nullable
public static native GeckoCheat[] downloadCodes(String gameTdbId);
}
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
import androidx.annotation.Keep
class GeckoCheat : AbstractCheat {
@Keep
private val mPointer: Long
constructor() {
mPointer = createNew()
}
@Keep
private constructor(pointer: Long) {
mPointer = pointer
}
external fun finalize()
private external fun createNew(): Long
override fun equals(other: Any?): Boolean {
return other != null && javaClass == other.javaClass && equalsImpl(other as GeckoCheat)
}
override fun hashCode(): Int {
return mPointer.hashCode()
}
override fun supportsCreator(): Boolean {
return true
}
override fun supportsNotes(): Boolean {
return true
}
external override fun getName(): String
external override fun getCreator(): String
external override fun getNotes(): String
external override fun getCode(): String
external override fun getUserDefined(): Boolean
external override fun getEnabled(): Boolean
private external fun equalsImpl(other: GeckoCheat): Boolean
external override fun setCheatImpl(
name: String,
creator: String,
notes: String,
code: String
): Int
external override fun setEnabledImpl(enabled: Boolean)
companion object {
@JvmStatic
external fun loadCodes(gameId: String, revision: Int): Array<GeckoCheat>
@JvmStatic
external fun saveCodes(gameId: String, revision: Int, codes: Array<GeckoCheat>)
@JvmStatic
external fun downloadCodes(gameTdbId: String): Array<GeckoCheat>?
}
}
@@ -1,61 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class GraphicsMod extends ReadOnlyCheat
{
@Keep
private final long mPointer;
// When a C++ GraphicsModGroup object is destroyed, it also destroys the GraphicsMods it owns.
// To avoid getting dangling pointers, we keep a reference to the GraphicsModGroup here.
@Keep
private final GraphicsModGroup mParent;
@Keep
private GraphicsMod(long pointer, GraphicsModGroup parent)
{
mPointer = pointer;
mParent = parent;
}
public boolean supportsCreator()
{
return true;
}
public boolean supportsNotes()
{
return true;
}
public boolean supportsCode()
{
return false;
}
@NonNull
public native String getName();
@NonNull
public native String getCreator();
@NonNull
public native String getNotes();
public boolean getUserDefined()
{
// Technically graphics mods can be user defined, but we don't support editing graphics mods
// in the GUI, and editability is what this really controls
return false;
}
public native boolean getEnabled();
@Override
protected native void setEnabledImpl(boolean enabled);
}
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
import androidx.annotation.Keep
class GraphicsMod @Keep private constructor(
@Keep private val pointer: Long,
// When a C++ GraphicsModGroup object is destroyed, it also destroys the GraphicsMods it owns.
// To avoid getting dangling pointers, we keep a reference to the GraphicsModGroup here.
@Keep private val parent: GraphicsModGroup
) : ReadOnlyCheat() {
override fun supportsCreator(): Boolean = true
override fun supportsNotes(): Boolean = true
override fun supportsCode(): Boolean = false
external override fun getName(): String
external override fun getCreator(): String
external override fun getNotes(): String
// Technically graphics mods can be user defined, but we don't support editing graphics mods
// in the GUI, and editability is what this really controls
override fun getUserDefined(): Boolean = false
external override fun getEnabled(): Boolean
external override fun setEnabledImpl(enabled: Boolean)
}
@@ -1,27 +0,0 @@
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
public class GraphicsModGroup
{
@Keep
private final long mPointer;
@Keep
private GraphicsModGroup(long pointer)
{
mPointer = pointer;
}
@Override
public native void finalize();
@NonNull
public native GraphicsMod[] getMods();
public native void save();
@NonNull
public static native GraphicsModGroup load(String gameId);
}
@@ -0,0 +1,17 @@
package org.dolphinemu.dolphinemu.features.cheats.model
import androidx.annotation.Keep
class GraphicsModGroup @Keep private constructor(@field:Keep private val pointer: Long) {
external fun finalize()
val mods: Array<GraphicsMod>
external get
external fun save()
companion object {
@JvmStatic
external fun load(gameId: String): GraphicsModGroup
}
}
@@ -1,60 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
public class PatchCheat extends AbstractCheat
{
@Keep
private final long mPointer;
public PatchCheat()
{
mPointer = createNew();
}
@Keep
private PatchCheat(long pointer)
{
mPointer = pointer;
}
@Override
public native void finalize();
private native long createNew();
public boolean supportsCreator()
{
return false;
}
public boolean supportsNotes()
{
return false;
}
@NonNull
public native String getName();
@NonNull
public native String getCode();
public native boolean getUserDefined();
public native boolean getEnabled();
@Override
protected native int trySetImpl(@NonNull String name, @NonNull String creator,
@NonNull String notes, @NonNull String code);
@Override
protected native void setEnabledImpl(boolean enabled);
@NonNull
public static native PatchCheat[] loadCodes(String gameId, int revision);
public static native void saveCodes(String gameId, int revision, PatchCheat[] codes);
}
@@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
import androidx.annotation.Keep
class PatchCheat : AbstractCheat {
@Keep
private val pointer: Long
constructor() {
pointer = createNew()
}
@Keep
private constructor(pointer: Long) {
this.pointer = pointer
}
external fun finalize()
private external fun createNew(): Long
override fun supportsCreator(): Boolean {
return false
}
override fun supportsNotes(): Boolean {
return false
}
external override fun getName(): String
external override fun getCode(): String
external override fun getUserDefined(): Boolean
external override fun getEnabled(): Boolean
external override fun setCheatImpl(
name: String,
creator: String,
notes: String,
code: String
): Int
external override fun setEnabledImpl(enabled: Boolean)
companion object {
@JvmStatic
external fun loadCodes(gameId: String, revision: Int): Array<PatchCheat>
@JvmStatic
external fun saveCodes(gameId: String, revision: Int, codes: Array<PatchCheat>)
}
}
@@ -1,36 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public abstract class ReadOnlyCheat implements Cheat
{
private Runnable mChangedCallback = null;
public int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes,
@NonNull String code)
{
throw new UnsupportedOperationException();
}
public void setEnabled(boolean enabled)
{
setEnabledImpl(enabled);
onChanged();
}
public void setChangedCallback(@Nullable Runnable callback)
{
mChangedCallback = callback;
}
protected void onChanged()
{
if (mChangedCallback != null)
mChangedCallback.run();
}
protected abstract void setEnabledImpl(boolean enabled);
}
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.model
abstract class ReadOnlyCheat : Cheat {
private var onChangedCallback: Runnable? = null
override fun setCheat(
name: String,
creator: String,
notes: String,
code: String
): Int {
throw UnsupportedOperationException()
}
override fun setEnabled(isChecked: Boolean) {
setEnabledImpl(isChecked)
onChanged()
}
override fun setChangedCallback(callback: Runnable?) {
onChangedCallback = callback
}
protected fun onChanged() {
if (onChangedCallback != null) onChangedCallback!!.run()
}
protected abstract fun setEnabledImpl(enabled: Boolean)
}
@@ -1,68 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.ui;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProvider;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding;
import org.dolphinemu.dolphinemu.features.cheats.model.ARCheat;
import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel;
import org.dolphinemu.dolphinemu.features.cheats.model.GeckoCheat;
import org.dolphinemu.dolphinemu.features.cheats.model.PatchCheat;
public class ActionViewHolder extends CheatItemViewHolder implements View.OnClickListener
{
private final TextView mName;
private CheatsActivity mActivity;
private CheatsViewModel mViewModel;
private int mString;
private int mPosition;
public ActionViewHolder(@NonNull ListItemSubmenuBinding binding)
{
super(binding.getRoot());
mName = binding.textSettingName;
binding.getRoot().setOnClickListener(this);
}
public void bind(CheatsActivity activity, CheatItem item, int position)
{
mActivity = activity;
mViewModel = new ViewModelProvider(activity).get(CheatsViewModel.class);
mString = item.getString();
mPosition = position;
mName.setText(mString);
}
public void onClick(View root)
{
if (mString == R.string.cheats_add_ar)
{
mViewModel.startAddingCheat(new ARCheat(), mPosition);
mViewModel.openDetailsView();
}
else if (mString == R.string.cheats_add_gecko)
{
mViewModel.startAddingCheat(new GeckoCheat(), mPosition);
mViewModel.openDetailsView();
}
else if (mString == R.string.cheats_add_patch)
{
mViewModel.startAddingCheat(new PatchCheat(), mPosition);
mViewModel.openDetailsView();
}
else if (mString == R.string.cheats_download_gecko)
{
mActivity.downloadGeckoCodes();
}
}
}
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.features.cheats.ui
import android.view.View
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding
import org.dolphinemu.dolphinemu.features.cheats.model.ARCheat
import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel
import org.dolphinemu.dolphinemu.features.cheats.model.GeckoCheat
import org.dolphinemu.dolphinemu.features.cheats.model.PatchCheat
class ActionViewHolder(binding: ListItemSubmenuBinding) : CheatItemViewHolder(binding.root),
View.OnClickListener {
private val mName: TextView
private lateinit var activity: CheatsActivity
private lateinit var viewModel: CheatsViewModel
private var string = 0
private var position = 0
init {
mName = binding.textSettingName
binding.root.setOnClickListener(this)
}
override fun bind(activity: CheatsActivity, item: CheatItem, position: Int) {
this.activity = activity
viewModel = ViewModelProvider(this.activity)[CheatsViewModel::class.java]
string = item.string
this.position = position
mName.setText(string)
}
override fun onClick(root: View) {
when(string) {
R.string.cheats_add_ar -> {
viewModel.startAddingCheat(ARCheat(), position)
viewModel.openDetailsView()
}
R.string.cheats_add_gecko -> {
viewModel.startAddingCheat(GeckoCheat(), position)
viewModel.openDetailsView()
}
R.string.cheats_add_patch -> {
viewModel.startAddingCheat(PatchCheat(), position)
viewModel.openDetailsView()
}
R.string.cheats_download_gecko -> activity.downloadGeckoCodes()
}
}
}

Some files were not shown because too many files have changed in this diff Show More