Skip to content
Permalink
Browse files
Merge pull request #10885 from JosJuice/android-graphics-mods
Android: Add graphics mods support to GUI
  • Loading branch information
JosJuice committed Jul 26, 2022
2 parents a9edf12 + 3bd2bca commit 9710029
Show file tree
Hide file tree
Showing 24 changed files with 477 additions and 48 deletions.
@@ -3,11 +3,13 @@
package org.dolphinemu.dolphinemu.features.cheats.model;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public abstract class AbstractCheat implements Cheat
public abstract class AbstractCheat extends ReadOnlyCheat
{
private Runnable mChangedCallback = null;
public boolean supportsCode()
{
return true;
}

public int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes,
@NonNull String code)
@@ -38,25 +40,6 @@ public int trySet(@NonNull String name, @NonNull String creator, @NonNull String
return result;
}

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 int trySetImpl(@NonNull String name, @NonNull String creator,
@NonNull String notes, @NonNull String code);

protected abstract void setEnabledImpl(boolean enabled);
}
@@ -17,6 +17,8 @@

boolean supportsNotes();

boolean supportsCode();

@NonNull
String getName();

@@ -33,7 +35,10 @@ default String getNotes()
}

@NonNull
String getCode();
default String getCode()
{
return "";
}

int trySet(@NonNull String name, @NonNull String creator, @NonNull String notes,
@NonNull String code);
@@ -24,10 +24,13 @@ public class CheatsViewModel extends ViewModel
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;
@@ -37,13 +40,23 @@ 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);
@@ -62,6 +75,12 @@ public void load(String gameID, int revision)

public void saveIfNeeded(String gameID, int revision)
{
if (mGraphicsModsNeedSaving)
{
mGraphicsModGroup.save();
mGraphicsModsNeedSaving = false;
}

if (mPatchCheatsNeedSaving)
{
PatchCheat.saveCodes(gameID, revision, mPatchCheats.toArray(new PatchCheat[0]));
@@ -280,6 +299,11 @@ public void openDetailsView()
mOpenDetailsViewEvent.setValue(false);
}

public ArrayList<GraphicsMod> getGraphicsMods()
{
return mGraphicsMods;
}

public ArrayList<PatchCheat> getPatchCheats()
{
return mPatchCheats;
@@ -0,0 +1,61 @@
// 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,27 @@
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,36 @@
// 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);
}
@@ -31,6 +31,7 @@ public class CheatDetailsFragment extends Fragment
private EditText mEditCreator;
private TextView mLabelNotes;
private EditText mEditNotes;
private TextView mLabelCode;
private EditText mEditCode;
private Button mButtonDelete;
private Button mButtonEdit;
@@ -59,6 +60,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
mEditCreator = view.findViewById(R.id.edit_creator);
mLabelNotes = view.findViewById(R.id.label_notes);
mEditNotes = view.findViewById(R.id.edit_notes);
mLabelCode = view.findViewById(R.id.label_code);
mEditCode = view.findViewById(R.id.edit_code);
mButtonDelete = view.findViewById(R.id.button_delete);
mButtonEdit = view.findViewById(R.id.button_edit);
@@ -158,10 +160,13 @@ private void onSelectedCheatUpdated(@Nullable Cheat cheat)

int creatorVisibility = cheat != null && cheat.supportsCreator() ? View.VISIBLE : View.GONE;
int notesVisibility = cheat != null && cheat.supportsNotes() ? View.VISIBLE : View.GONE;
int codeVisibility = cheat != null && cheat.supportsCode() ? View.VISIBLE : View.GONE;
mLabelCreator.setVisibility(creatorVisibility);
mEditCreator.setVisibility(creatorVisibility);
mLabelNotes.setVisibility(notesVisibility);
mEditNotes.setVisibility(notesVisibility);
mLabelCode.setVisibility(codeVisibility);
mEditCode.setVisibility(codeVisibility);

boolean userDefined = cheat != null && cheat.getUserDefined();
mButtonDelete.setEnabled(userDefined);
@@ -13,6 +13,7 @@
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.GraphicsMod;
import org.dolphinemu.dolphinemu.features.cheats.model.PatchCheat;

import java.util.ArrayList;
@@ -90,8 +91,8 @@ public void onBindViewHolder(@NonNull CheatItemViewHolder holder, int position)
@Override
public int getItemCount()
{
return mViewModel.getARCheats().size() + mViewModel.getGeckoCheats().size() +
mViewModel.getPatchCheats().size() + 7;
return mViewModel.getGraphicsMods().size() + mViewModel.getPatchCheats().size() +
mViewModel.getARCheats().size() + mViewModel.getGeckoCheats().size() + 8;
}

@Override
@@ -108,6 +109,17 @@ private void addViewListeners(View view)

private CheatItem getItemAt(int position)
{
// Graphics mods

if (position == 0)
return new CheatItem(CheatItem.TYPE_HEADER, R.string.cheats_header_graphics_mod);
position -= 1;

ArrayList<GraphicsMod> graphicsMods = mViewModel.getGraphicsMods();
if (position < graphicsMods.size())
return new CheatItem(graphicsMods.get(position));
position -= graphicsMods.size();

// Patches

if (position == 0)
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.cheats.ui;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;

public class CheatsDisabledWarningFragment extends SettingDisabledWarningFragment
{
public CheatsDisabledWarningFragment()
{
super(BooleanSetting.MAIN_ENABLE_CHEATS, MenuTag.CONFIG_GENERAL,
R.string.cheats_disabled_warning);
}
}
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.cheats.ui;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;

public class GraphicsModsDisabledWarningFragment extends SettingDisabledWarningFragment
{
public GraphicsModsDisabledWarningFragment()
{
super(BooleanSetting.GFX_MODS_ENABLE, MenuTag.ADVANCED_GRAPHICS,
R.string.gfx_mods_disabled_warning);
}
}

0 comments on commit 9710029

Please sign in to comment.